1

我在数据绑定和实体框架的导航属性方面遇到了一些问题。

我有两个类,由实体框架设计器生成:

Foo 类

id (int)
bar (Bar)
...

班级酒吧

id (int)
name (string)
...

使用ObservableCollection<Foo>,我用以下列填充了数据网格:

<DataGrid.Columns>
    <DataGridTextColumn Header="Id" Binding="{Binding Path=id}"/>
    <DataGridTemplateColumn Header="Bar">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox 
                    SelectedValuePath="Id" 
                    SelectedValue=
                        "{Binding Path=bar.Id, Mode=TwoWay,
                        UpdateSourceTrigger=PropertyChanged}"
                    DisplayMemberPath="name" 
                    ItemsSource=
                        "{Binding Path=BarList, 
                        RelativeSource={RelativeSource FindAncestor, 
                        AncestorType={x:Type Window}}}"
                    Background="White" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>

ComboBox 填充了一个ObservableCollection<Bar>并且正确显示了当前的Bar.

当我在组合框中选择另一个项目时,问题就来了。我收到以下错误:

System.Windows.Data Error: 8 : Cannot save value from target back to source.

System.InvalidOperationException: The property 'Id' is part of the object's key information and cannot be modified

我可以看到为什么会弹出错误,但是我该如何以不同的方式处理呢?

Foo编辑: and之间的关系Bar是 N..1,这意味着 aFoo有 1 或 0Bar而 Bar 可以有几个Foos。

目前,我无法Bar为我Foo的 s 选择新的。

4

3 回答 3

2

您必须bar直接绑定属性。您的代码尝试更改Id所选 Foo 条上的 ,但您想要更改与当前 Foo 关联的条。您还必须覆盖类Equals的方法Bar

<ComboBox SelectedValue="{Binding bar, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
          DisplayMemberPath="Name"
          ItemsSource="{Binding Path=BarList, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Background="White" />

在你的Bar课堂上:

public override bool Equals(object obj)
{
    if (obj is Bar)
        return ((Bar)obj).Id == Id;
    return false;
}
于 2012-11-19T11:57:08.157 回答
2

如果您不想直接使用对象来执行此操作(这意味着不使用SelectedValuePathandSelectedValue而是SelectedItem="{Binding Foo.Bar}"直接使用,您需要指示 EF 设计器使用generate foreign key property BarId on the Foo entity,然后您可以绑定SelectedValue="{Binding Foo.BarId}".

于 2012-11-19T20:07:43.030 回答
0

在我看来,实体框架的问题比 WPF 的问题更多。bar 的 id 同时是 foo 主键的一部分是否正确?至少绑定、组合框的设置和错误消息似乎暗示了这一点。

实体框架的限制之一是它不支持密钥更新。如果要更改对象的键,则基本上必须删除它,使用新键重新创建它,然后复制所有其他属性。在我目前正在处理的程序中,我决定创建一个包装类,它将 Id 作为属性公开,并在更改时在幕后进行处理。我已经看到建议只分离对象并重用它的帖子,但在我的情况下这不起作用。

于 2012-11-19T18:58:38.653 回答