【问题标题】:MVVM WPF: Remove element from DataGridComboBoxColumn based on selected itemMVVM WPF:根据所选项目从 DataGridComboBoxColumn 中删除元素
【发布时间】:2020-07-01 08:11:42
【问题描述】:

目前我有一个包含一些列的数据网格。这些列之一是 DataGridComboBoxColumn。 这绑定到两个类。 SelectedValueBinding 绑定到名为 HMDGroup 的模型类属性。项目源绑定到我的 ViewModel 中名为 HMDGroups 的列表;

我正在寻找一种方法从组合框中的列表中删除一个项目,基于是否已在同一列的另一个组合框中选择了相同的项目。

例如,我已经为两个单元格选择了 136b6407 和 136b6408,应该无法在下一个单元格中再次选择它们,除非将其从其他单元格中删除。

Image showing example

我对 MVVM 模式很陌生,不知道如何用 MVVM 方式解决这个问题,因为它绑定到一个列表。

非常感谢您的帮助!

XAML:

<DataGrid Name="VariantHandlerDatagrid" AutoGenerateColumns="False" Grid.ColumnSpan="3" Grid.RowSpan="1" ItemsSource="{Binding variantHandlerItems}" SelectionUnit="Cell" CanUserReorderColumns="False" CanUserDeleteRows="False" CanUserAddRows="False" IsReadOnly="False" GridLinesVisibility="None"
              HeadersVisibility="Column" CanUserSortColumns="True" HorizontalAlignment="Left" Height="auto" VerticalAlignment="Top" Width="auto" ColumnWidth="*" >
       <DataGrid.Resources>
            <local:VHViewModel x:Key="ComboItems"/>
       </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Variant Name" Binding="{Binding Variant}" IsReadOnly="True"/>
            <DataGridComboBoxColumn x:Name="hmdComboCol" Header="HMD Group" 
                                    SelectedValueBinding="{Binding HMDGroup, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                                    ItemsSource="{Binding Path=HMDGroups, Source={StaticResource ComboItems}}"/> 
         </DataGrid.Columns>

</DataGrid>

视图模型:

 sealed class VHViewModel : INotifyPropertyChanged
{
   
    private List<string> usedHMDGroups = new List<string>();
    private List<string> startHMDGroups = new List<string>{
                "136b6405",
                "136b6406",
                "136b6407",
                "136b6408",
                "136b6409",
                "136b6410",
                "None"
            };

    public List<string> HMDGroups
    {
        get 
        {
            return startHMDGroups;
            
        }
        set 
        {
            startHMDGroups = value;
            OnPropertyChange("HMDGroups");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChange(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

型号:

sealed class VariantMapping : INotifyPropertyChanged
{
    private string hmdGroup;

    public string HMDGroup
    {
        get { return hmdGroup; }
        set
        {
            hmdGroup = value;
            if (String.IsNullOrEmpty(hmdGroup))
            {
                if (String.IsNullOrEmpty(smdGroup))
                {
                    variant = "None";
                    OnPropertyChange("Variant");
                    OnPropertyChange("HMDGroup");
                }
                else
                {
                    variant = smdGroup;
                    OnPropertyChange("Variant");
                    OnPropertyChange("HMDGroup");
                }
            }
            else
            {
                variant = hmdGroup;
                OnPropertyChange("Variant");
                OnPropertyChange("HMDGroup");
            }
        }
    }

   
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChange(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

【问题讨论】:

  • 您通过将视图绑定到模型来破坏 MVVM。视图不应该知道模型的存在。
  • @Bizhan 我应该如何绑定列以获得单元格中的正确值?
  • 这里的关键是在 HDMGroup 属性的设置器中添加逻辑,以便在调用时从 HMDGroups 集合中删除该项目。您的 HMDGroups 集合也必须是 ObservableCollection 而不是 List,因为列表不会在删除或添加项目时通知 UI。
  • 遵守 MVVM 原则。 V &lt;-&gt; VM -&gt; M。通常您需要为视图的每个部分实现一个虚拟机。并在每个 VM 中提供读取或写入模型的逻辑。有时为了方便起见,最好将 Model 的引用保留在 VM 中。但是您需要对模型的状态保持谨慎,以确保它没有过时

标签: c# wpf xaml mvvm datagridcomboboxcolumn


【解决方案1】:

您必须使用 ComboBox 中的 SelectedValue 与值 136b6407 和绑定到另一个 ComboBox 的列表。

一些提示。

方式 1

通过删除绑定列表中的选定项,让主 Grid ViewModel 将 ComboBox 的 SelectedValue 与值 136b6407 同步到另一个 ComboBox。这种方式有些无聊,因为您需要实现一种机制来手动同步绑定到ComboBoxes 的 2 ViewModel

方式 2

这个解决方案可以让您更好地维护代码,并且还可以让您编写比第一个解决方案更少的代码。

您需要使用 Message Broker 设计模式https://en.wikipedia.org/wiki/Message_broker,您可以实现自己的 Message Broker,或者简单地使用任何已经实现它的 MVVM Toolkit 库之一。大多数现有的 MVVM 工具包都有自己的 Message Broker 实现。所以不需要重新发明。

例如,MVVM Light Toolkit Message Broker 在这里解释:https://docs.microsoft.com/en-us/archive/msdn-magazine/2014/june/mvvm-the-mvvm-light-messenger-in-depth#using-messages

因此,当 ComboBox 的 SelectedValue 的值为 136b6407 绑定到其他 ComboBox 时,您可以让代理发送一条消息,可以订阅此消息并做出反应,从其自己的绑定列表中删除该项目。

要获得更多信息,请查看引用此解决方案的 SO 上的答案:How to change specific property in an element of an Observable Collection on PropertyChange?

【讨论】:

  • 感谢您的回答,我会调查并回复。
  • 你告诉我玩组合框的值和绑定到另一个组合框的列表。同一个列表绑定到所有组合框。因此,如果我从列表中删除 selectedvalue 字符串,它只会使组合框变为空白。这里有什么解决办法?
  • @BenjaminMadsen:您可以在需要时致电&lt;your_observablecollection&gt;.ToList() 克隆它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-22
  • 2011-03-25
  • 1970-01-01
  • 2015-02-18
  • 2016-05-10
相关资源
最近更新 更多