繁体   English   中英

EF EntityObject 不更新关系的数据绑定

[英]EF EntityObject not updating databindings of relationships

我在我的应用程序中使用 EntityFramework、WPF 和 MVVM,但在更新 EntityObjects 之间关系的数据绑定时遇到了一些问题。 我能够将我的问题缩小到只有几行 XAML 并且我希望有人可以帮助我,因为我对 EF 和 MVVM 仍然不是很有信心。

无论如何,这里我们 go 和简化的 XAML:

    <DatePicker Grid.Row="2" Grid.Column="1" 
                    SelectedDate="{Binding Path=File.SentDate, 
StringFormat={}{0:dd/MM/yyyy}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                    VerticalAlignment="Center" IsEnabled="{Binding Path=IsEnabled}"/>

        <ComboBox Grid.Row="3" Grid.Column="1" ItemsSource="{Binding Contacts}" DisplayMemberPath="Name" 
                  SelectedItem="{Binding Path=File.Sender, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEditable="True"
                  VerticalAlignment="Center">
        </ComboBox>

        <Label Content="{Binding Path=File.SenderId}" Grid.Row="4"/>
        <Label Content="{Binding Path=File.Sender.Name}" Grid.Row="5"/>
        <Label Content="{Binding Path=File.SentDate}" Grid.Row="6"/>

我正在使用最后 3 个标签来测试我的数据绑定。 使用 DatePicker 更改 File.SentDate 将数据绑定更新到最后的 Label 没有问题。

现在 File 是 EntityObject 类型,并且具有 GUID 类型的 SenderId 属性。 它还通过 Sender 属性与我的联系人有关系。 显然,SenderId 是通过 Sender 关系与 File 相关的对应 Contact EntityObject 的 GUID。 一个文件只能有 1 个联系人类型的发件人。

无论如何,发生的情况是,当我 select 另一个发件人使用 combobox 时,显示 File.SenderId 属性的 Label 得到正确更新。 但是,具有 File.Sender.Name 属性的那个,即使用关系的那个没有得到更新。

所以我猜想在 EF 中更新关系的数据绑定有一些特别之处。

有人可以提出解决方案吗?

不幸的是,实体框架不会在关联属性更改时发出通知。 这就是您的绑定不起作用的原因。

该问题已报告给 Microsoft: http://connect.microsoft.com/VisualStudio/feedback/details/532257/entity-framework-navigation-properties-don-t-raise-the-propertychanged-event

WPF 应用程序框架 (WAF)BookLibrary示例应用程序显示了另一种解决方法。 Book class 监听 AssociationChanged 事件并引发相应的 PropertyChanged 事件。

public Book()
{
    …
    LendToReference.AssociationChanged += LendToReferenceAssociationChanged;
}

private void LendToReferenceAssociationChanged(object sender, 
        CollectionChangeEventArgs e)
{
    // The navigation property LendTo doesn't support the PropertyChanged event. 
    // We have to raise it ourselves.
    OnPropertyChanged("LendTo");
}

如果您只是想要一个名称,另一种解决方法是覆盖 Sender 的 ToString() 并直接绑定到发件人。 这种解决方法很好,因为大多数时候我们将数据绑定到属性的属性时,我们这样做是为了将 object 的“名称”设置为属性值。 如果您编辑 tt 文件以将部分添加到所有 class 定义,则此方法也适用于数据库优先方法。

因此,您添加一个文件以包含您的实体的 ToString 扩展名,并在其中添加如下内容:

public partial Contacts 
{
    public override string ToString()
    {
        return Name;
    }
}

所以你可以数据绑定

<Label Content="{Binding Path=File.Sender}" Grid.Row="5"/>

现在数据绑定将检测 Sender 是否更改,当它发生更改时,它将调用 ToString 以确定要显示的内容。

另一方面,如果您需要绑定到另一个非标准属性,您可能会遇到问题。 我确实记得成功使用 DataContext 和模板来解决它。 您绑定到 Sender 并使用 DataTemplate 来确定要显示的内容。

看起来我已经找到了解决方案,尽管对我来说它更像是一种解决方法。 这不是我所期望的解决方案,但它有效。

XAML 还是和上面一样,除了一件事。 我没有绑定到 File.Sender.Name,而是像这样绑定到 File.SenderName:

<Label Content="{Binding Path=File.SenderName}" Grid.Row="4"/>

在这种情况下,SenderName 是 object 文件的属性,我在部分 class 中添加了该文件,如下所示:

public partial class File
{
        public string SenderName
        {
            get
            {
                if (this.Sender != null)
                {
                    return this.Sender.Name;
                }

                return string.Empty;
            }
        }
protected override void OnPropertyChanged(string property)
        {

            if (property == "SenderId")
            {
                OnPropertyChanged("SenderName");
            }
            base.OnPropertyChanged(property);
        }
}

所以这里发生的情况是,如果 SenderId 属性发生更改,我会告诉框架也更新 SenderName 属性。 而已。 奇迹般有效。 尽管我仍然不相信这是它应该工作的方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM