如何使用MVVM将DataGridComboBoxColumn绑定到EntityFramework?

时间:2012-02-16 21:54:12

标签: wpf vb.net entity-framework mvvm

我正在尝试使用我的ViewModel使用DataGridComboBoxColumn。一切似乎都正常工作,但当我更改组合框的值时,实体不会更改。

窗口的datacontext具有以下属性:

的ItemsSource

Public Property AllEnergySources() As ObservableCollection(Of EnergySourceViewModel)

SelectedItemBinding

  Private _CurrentEnergySource As EnergySourceViewModel
    Public Property CurrentEnergySource() As EnergySourceViewModel
        Get
            Return _CurrentEnergySource
        End Get
        Set(ByVal value As EnergySourceViewModel)
            _CurrentEnergySource = value
            OnPropertyChanged("CurrentEnergySource")
        End Set
    End Property

我觉得问题在于如何在ViewModel中填充DataContext的CurrentEnergySource:

Sub New(SelectedEntity as EquipmentEnergySource)
     AllEnergySources = New ObservableCollection(Of EnergySourceViewModel)

    //Select all EnergySources from the EntityFramework
     Dim EnergyEntities = From esr in db.EnergySources Select esr

                //Loop through to convert Entity POCO to Collection of ViewModels
                For Each es In EnergyEntities
                    _AllEnergySources.Add(New EnergySourceViewModel(es))

                    //Optionally Set the newly created ViewModel to SelectedItemBinding object
                    If es.EnergySourceID = SelectedEntity.EnergySourceID Then
                        _CurrentEnergySource = _AllEnergySources.Last
                    End If
                Next
End Sub

当我为组合框创建支持集合时,如果模型是选定的模型,我将该视图模型设置为CurrentEnergySource,但在此之后它将断开连接(这就是问题)

我应该在CurrentEnergySource中引用什么,以便在组合框更改时更新模型?

4 个答案:

答案 0 :(得分:1)

似乎错误的一件事是你应该使用SelectedValueBinding而不是SelectedItemBinding。

这是一个适合我的样本:

<Page.Resources>
    <ViewModel:DataGridComboBoxViewModel x:Key="model"/>
    <Style x:Key="ElementStyle" TargetType="ComboBox">
        <Setter 
            Property="ItemsControl.ItemsSource" 
            Value="{Binding Path=DataContext.DetailItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" 
            />
    </Style>
</Page.Resources>

<Grid DataContext="{StaticResource model}">
    <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
            <DataGridComboBoxColumn Header="Combo" 
                                    DisplayMemberPath="Name" 
                                    SelectedValueBinding="{Binding DetailItem}" 
                                    ElementStyle="{StaticResource ElementStyle}"
                                    EditingElementStyle="{StaticResource ElementStyle}"
                                    >
            </DataGridComboBoxColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

public class DataItem : ViewModelBase
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; } 

    private DetailItem _detailItem;
    public DetailItem DetailItem
    {
        get { return _detailItem; }
        set
        {
            Debug.WriteLine(value != null
                                ? string.Format("Setting detail item to: {0}", value.Name)
                                : "Setting detail item to null.");

            Set(() => DetailItem, ref _detailItem, value);
        }
    }
}

public class DetailItem : ViewModelBase
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class DataGridComboBoxViewModel : ViewModelBase
{
    public DataGridComboBoxViewModel()
    {
        DetailItems = new List<DetailItem>
                          {
                              new DetailItem {Id = 0, Name = "Zero"},
                              new DetailItem {Id = 1, Name = "One"},
                              new DetailItem {Id = 2, Name = "Two"},
                              new DetailItem {Id = 3, Name = "Three"},
                          };

        Items = new List<DataItem>
                    {
                        new DataItem {Id = 0, Name = "Item 1", Description = "This is item 1"},
                        new DataItem {Id = 1, Name = "Item 2", Description = "This is item 2"},
                        new DataItem {Id = 2, Name = "Item 3", Description = "This is item 3"},
                        new DataItem {Id = 3, Name = "Item 4", Description = "This is item 4"},
                    };
    }

    public List<DataItem> Items { get; set; }
    public List<DetailItem> DetailItems { get; private set; }
}

答案 1 :(得分:0)

当然,问题出在你的绑定中,DataGridComboBoxColumn会自动从CurrentEnergySource中获取一个项目,而CurrentEnergySource上没有AllEnergySources,乳清你不会轻易使用它,

            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding SelectedItemFromItemsSource}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding ItemsSource}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>

答案 2 :(得分:0)

您是否在绑定上尝试过RelativeSource?通常我发现当我绑定到模板中的列等时,绑定会查看控件的绑定内部,而不是视图的datacontext的绑定。

尝试:

"{Binding Path=DataContext.CurrentEnergySource, 
          RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},
          Mode=TwoWay}"

"{Binding ElementName=NameOfTheView, 
          Path=DataContext.CurrentEnergySource, 
          Mode=TwoWay}"

然后将x:Name="NameOfTheView"添加到View的属性中(位于&gt;括号内的xmlns位置下方)

答案 3 :(得分:0)

我的回答是您需要手动更改外键(我现在在CurrentEnergySource的setter中更改它,这是SelectedItemBinding绑定属性)

     Private _CurrentEnergySource As EnergySourceViewModel
    Public Property CurrentEnergySource() As EnergySourceViewModel
        Get
            Return _CurrentEnergySource
        End Get
        Set(ByVal value As EnergySourceViewModel)
            _CurrentEnergySource = value
            Me.Model.EnergySourceID = value.Model.EnergySourceID
            OnPropertyChanged("CurrentEnergySource")
        End Set
    End Property

在加载时,填充私有后备存储_CurrentEnergySource而不是属性,以避免所有以修改状态开始的对象