DataBinding 不适用于 DataGrid 中的 Combobox

Posted

技术标签:

【中文标题】DataBinding 不适用于 DataGrid 中的 Combobox【英文标题】:DataBinding not working for Combobox in DataGrid 【发布时间】:2016-04-13 09:21:43 【问题描述】:

这个快把我逼疯了……

这是我用来绑定数据网格中列中的组合框的 xaml。 ItemSource 指向持有“Pipetter”类的 ObservableCollection。 CellTemplate,只需要显示当前选中行的这个 Pipetter 类的“name”属性。

问题是,一旦我在组合框中选择了一个值,所选择的值就会突然出现在该列的所有行中。我已经以许多不同的方式重新设计了这些方法,并且在每种情况下都发生了这种情况。关于关闭什么设置的任何想法?

<DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
        <ComboBox 
            IsEditable="False"  
            ItemsSource="Binding DataContext.Pipettors, RelativeSource=RelativeSource AncestorType=x:Type DataGrid, Mode=TwoWay"
            SelectedItem="Binding DataContext.SelectedPipettor, RelativeSource=RelativeSource AncestorType=x:Type DataGrid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" 
            SelectedValue="Binding TipGroup.PipettorTipType.Pipettor"
            DisplayMemberPath="Name"
            />
    </DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Label 
            Content="Binding TipGroup.PipettorTipType.Pipettor.Name" 
            Style="DynamicResource DataGridRowLabel" 
            />
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

这是选定项绑定到的 Vm 中的属性。我只是将“SelectedItem”分配给当前选定行(SelectedTipGroup)中的相应属性。这在 DataGrid 定义中被定义为“SelectedItem”。

 private Pipettor selectedPipettor;
    public Pipettor SelectedPipettor
    

        get  return selectedPipettor; 
        set
        
            SetProperty(ref selectedPipettor, value);
            SelectedTipGroup.TipGroup.PipettorTipType.Pipettor = value;
        
    

我按照建议更新了组合框绑定:

<DataGridTemplateColumn.CellEditingTemplate>
      <DataTemplate>
          <ComboBox x:Name="PipetterComboBox"
              ItemsSource= "Binding DataContext.Pipettors, RelativeSource=RelativeSource AncestorType=x:Type UserControl, Mode=TwoWay"
                                  SelectedItem="Binding TipGroup.PipettorTipType.Pipettor" IsSynchronizedWithCurrentItem="True"
                                  DisplayMemberPath="Name"
                                 />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>

                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label Content="Binding TipGroup.PipettorTipType.Pipettor.Name" Style="DynamicResource DataGridRowLabel" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

当在数据网格的一行中进行选择时,相同的值出现在该列的所有行中......它只是试图将 selectedItem 类分配给当前行中的类属性“Pipettor”。 ..

在这个上花了 DAYS 天.. 没有意义...

谢谢!

这是组合框绑定到的属性。组合框的 ItemsSource 只是 Pipettor 类型的 observablecollection。

  private Pipettor pipettor;
    [DataMember]
    public Pipettor Pipettor
    
        get  return this.pipettor; 
        set
        
            if (SetProperty(ref this.pipettor, value))
            
                //***BKM This was failing on delete - not sure if masking or not but will null check
                //note something similar in other models - review
                if (value != null)
                
                    this.pipettorId = this.pipettor.Identity;

                
            
        
    

和 SetProperty()

 protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    
        if (object.Equals(field, value)) 
         
            return false; 
        

        field = value;
        //Check to make sure Tracking is Initialized but no need to do anything
        if (!this.Tracking.Initialized)
        

        

        RaisePropertyChanged(propertyName);
        return true;
    

【问题讨论】:

也许在你的属性设置器中通知 IPropertyChanged? SetProperty 是做什么的? PropertyChanged 有没有机会被解雇? setproperty 只是封装了检查以查看新值是否为 != 当前值,如果是,则引发 propertyChanged 事件并将支持字段设置为新值。 【参考方案1】:

ComboBox 的 SelectedItem 正在使用 RelativeSource 来使用 DataGrid 的 DataContext,因此所有行都使用相同的 SelectedItem。将此更改为 DataGrid 中每一行的项中的绑定。看起来您可能已经在 SelectedValue 上拥有此绑定,看起来它确实应该在 SelectedItem 上。

SelectedValue 绑定无法按原样工作,因为未设置 SelectedValuePath。有关 SelectedItem 和 SelectedValue 之间的区别,请参阅此问题: Difference between SelectedItem, SelectedValue and SelectedValuePath

编辑:根据此答案更新问题后,IsSynchronizedWithCurrentItem="True" 已添加到组合框的 xaml 中。来自 MSDN 的有关此属性的文档:

"您可以将 IsSynchronizedWithCurrentItem 属性设置为 true,以确保选中的项始终对应于 ItemCollection 中的 CurrentItem 属性。例如,假设有两个 ListBox 控件的 ItemsSource 属性设置为相同的源。设置 IsSynchronizedWithCurrentItem在两个列表框中设置为 true,以确保每个 ListBox 中的选定项相同。"

将此设置为 true 这也会导致所有 ComboBox 使用相同的选择。从 ComboBox 的 xaml 中删除此属性。

MSDN 参考:https://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.selector.issynchronizedwithcurrentitem(v=vs.110).aspx

【讨论】:

我试过这样做,当我选择一个下拉值时,它仍在更新所有行:请参阅编辑... 您要绑定的 TipGroup.PipettorTipType.Pipettor 的代码是什么样的? 您在更新的 xaml 中添加了 IsSynchronizedWithCurrentItem="True"。这旨在将具有相同 ItemsSource 的多个选择同步到相同的 SelectedItem。删除它。 好的。如果您已将其删除,那么此时我认为问题不再存在于您的 xaml 中,并且我在您共享的其他代码中看不到任何问题。您应该尝试通过调试来确定是什么导致 Pipettor 属性在其他行中发生变化。 是的,经过更多挖掘,似乎原因是这些模型类使用了一个基类,该基类是为实现 EntityFramework 的跟踪而创建的。当我创建另一个没有继承自内部创建的 EF 基类的类时,它运行良好!我花了很多时间在这上面,我还没有找到确切的原因。我必须继续使用新的班级结构......到目前为止效果很好......谢谢!

以上是关于DataBinding 不适用于 DataGrid 中的 Combobox的主要内容,如果未能解决你的问题,请参考以下文章

Datagrid列自动填充不适用于自动生成的列

如何使用 .NET MAUI Preview 7 创建 DataGrid?

SpringMVC Databinding(数据绑定)

Android Databinding 数据绑定中经常出现的问题

所选行的 WPF DataGrid RowStyle 不改变背景和前景色

Android DataBinding笔记