【问题标题】:How do I bind a DataGridComboBoxColumn to EntityFramework using MVVM?如何使用 MVVM 将 DataGridComboBoxColumn 绑定到 EntityFramework?
【发布时间】:2012-02-16 21:54:12
【问题描述】:

我正在尝试让 DataGridComboBoxColumn 与我的 ViewModel 一起使用。一切似乎都正常工作,但是当我更改组合框的值时,实体没有改变。

窗口的数据上下文具有以下属性:

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 中填充 CurrentEnergySource,即 DataContext:

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 中引用什么,以便在组合框更改时更新模型?

【问题讨论】:

  • 你是否绑定了 TwoWay 并且 EnergySourceViewModel 是否实现了 INotifyPropertyChanged?
  • 是的,是的,但问题是我绑定到 (CurrentEnergySource) 的属性有自己的支持字段。属性应该获取/设置什么而不是支持字段?
  • 显示你是否绑定了 DataGridComboBoxColumn
  • 可能是个愚蠢的建议,但您是否尝试过将UpdateSourceTrigger=PropertyChanged 放入绑定中?

标签: wpf vb.net entity-framework mvvm


【解决方案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; }
}

【讨论】:

  • 对不起,应该提到我正在使用 MVVMLight。 Set 是设置属性和引发属性更改通知的助手。您可以替换为 _detailItem = value; RaisePropertyChanged("DetailItem"); (或您的等价物)。
【解决方案2】:

当然,问题出在你的绑定上,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>

【讨论】:

  • 这并不能回答我的问题,它只是转换为 DataGridTemplateColumn 而不是 DataGridComoBoxColumn。问题是我不知道 SelectedItemFromItemsSource 使用什么
【解决方案3】:

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

试试:

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

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

然后将x:Name="NameOfTheView"添加到视图的属性中(在>括号内的xmlns位置下方)

【讨论】:

    【解决方案4】:

    我的回答是你需要手动更改外键(我现在在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 而不是属性以避免所有对象以修改状态开始

    【讨论】:

      猜你喜欢
      • 2011-07-27
      • 2011-04-03
      • 2012-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 2011-07-10
      • 2011-12-21
      相关资源
      最近更新 更多