ObservableCollection更改时未更新DataGrid项

本文关键字:更新 DataGrid ObservableCollection | 更新日期: 2023-09-27 18:21:25

我有一个DataGrid,其中列中显示的值并不总是正确更新。

定义如下:

<uic:DataGridControlEx Grid.Row="1" 
                               ReadOnly="True" 
                               Name="m_dgErgaenzungsfelder" 
                               NavigationBehavior ="RowOnly"
                               SelectionMode="Extended"
                               AutoCreateColumns="False"
                               ItemsSource="{Binding Path=ErgaenzungsfelderEntities}"
                               SelectionChanged="OnDGSelectionChanged" >
    <uic:DataGridControlEx.View>
        <xc:TableView ColumnStretchMode="Last" 
                                  AllowColumnChooser="False" 
                                  VerticalGridLineThickness="0"
                                  UseDefaultHeadersFooters="False"
                                  ShowRowSelectorPane="False">
            <xc:TableView.FixedHeaders>
                <DataTemplate>
                    <xc:ColumnManagerRow/>
                </DataTemplate>
            </xc:TableView.FixedHeaders>
            <xc:TableView.Theme>
                <xc:Office2007SilverTheme />
            </xc:TableView.Theme>
        </xc:TableView>
    </uic:DataGridControlEx.View>
    <uic:DataGridControlEx.Columns>
        <xc:Column Title="{LocText FGG1:ErgaenzungsfelderResources:ErgaenzungsfelderViewColumnName}"
                           FieldName="Name" />
        <xc:Column Title="{LocText FGG1:ErgaenzungsfelderResources:ErgaenzungsfelderViewColumnType}"
                           FieldName="ErgaenzungsfeldType" >
            <xc:Column.CellContentTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=., Converter={x:Static converters:ErgaenzungsfeldTypeTotextConverter.Instance}}" />
                </DataTemplate>
            </xc:Column.CellContentTemplate>
        </xc:Column>
        <xc:Column Title="{LocText FGG1:ErgaenzungsfelderResources:ErgaenzungsfelderViewColumnAuthor}"
                           FieldName="Author" />
        <xc:Column Title="{LocText FGG1:ErgaenzungsfelderResources:ErgaenzungsfelderViewColumnCreationDate}"
                           FieldName="CreationDate" />
    </uic:DataGridControlEx.Columns>
</uic:DataGridControlEx>

DataGridControlEx排除了Xceed DataGridControl,但不影响绑定。

后面的代码包括网格绑定的ObservableCollection的定义、构造函数早期初始化集合以及更新项的方法:

public ObservableCollection<ErgaenzungsfeldEntity> ErgaenzungsfelderEntities { get; private set; }
public ErgaenzungsfelderView() {
   ErgaenzungsfelderEntities = new ObservableCollection<ErgaenzungsfeldEntity>();
   InitializeComponent();
}
public void ShowErgaenzungsfelder(List<ErgaenzungsfeldEntity> entities) {
   ErgaenzungsfelderEntities.Clear();
   entities.ForEach(e => ErgaenzungsfelderEntities.Add(e));
   //m_dgErgaenzungsfelder.GetBindingExpression(ItemsControl.ItemsSourceProperty).UpdateSource();
}

ErgaenzungsfeldEntity实现INotifyPropertyChanged,并为每次更改通知属性更改,例如:

public string Name {
   get { return m_name; }
   set {
      m_name = value;
      NotifyPropertyChanged("Name");
   }
}

当通过GUI更新绑定项目时,更改始终正确反映。通过GUI,不会使用上面提到的ShowErgaenzungsfelder重新加载项,而是将绑定项作为引用传递。

问题:我们的服务层可以通知需要重新加载元素的事件。这将调用ShowErgaenzungsfelder。执行此操作时,添加的实体将显示在网格中,删除的实体将被删除。但是,修改后的实体不会反映字段Name和ErgaenzungsfeldType(这是唯一可以更改的属性)的更改
例如,更改列排序将触发网格更新并显示正确的值。

对于`ItemsSource,我尝试更改所有这些属性,但没有成功:

ItemsSource="{Binding Path=ErgaenzungsfelderEntities, UpdateSourceTrigger=Explicit, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, Mode=OneWay}"

  • UpdateSourceTrigger=ShowErgaenzungsfelder中的显式且未注释的m_dgErgaenzungsfelder.GetBindingExpression(ItemsControl.ItemsSourceProperty).UpdateSource();
  • UpdateSourceTrigger=属性已更改
  • UpdateSourceTrigger=默认

如有任何意见,我将不胜感激。

ObservableCollection更改时未更新DataGrid项

这里有一些心理调试。

服务层引发的事件没有在GUI线程上运行,因此ShowErgaenzungsfelder函数也不在GUI线程中,也没有通过更改集合引发的事件。WPF将在非GUI线程上接收这些事件,然后尝试更新GUI,但由于不在GUI线程上进行更新而失败,并引发错误。WPF在生成异常时的行为是中止操作并隐藏异常,因此您什么也看不到。(在VisualStudio中,您可能会在"输出"面板中看到这些异常;有一个选项可以在那里显示它们。)

要测试这一点,您需要将更新发送到GUI线程。你可以这样做:

    public ObservableCollection<ErgaenzungsfeldEntity> ErgaenzungsfelderEntities { get; private set; }
    public ErgaenzungsfelderView() {
       ErgaenzungsfelderEntities = new ObservableCollection<ErgaenzungsfeldEntity>();
       InitializeComponent();
       // This will be called on the GUI thread
       this.guiContext = SynchronizationContext.Current;
   }
   private readonly SynchronizationContext guiContext;
   public void ShowErgaenzungsfelder(List<ErgaenzungsfeldEntity> entities) {
        this.guiContext.Send(this.ShowErgaenzungsfelderOnGuiThread, entities);
   }   
   private void ShowErgaenzungsfelderOnGuiThread(object state) {
       List<ErgaenzungsfeldEntity> entities = state as List<ErgaenzungsfeldEntity>;
       ErgaenzungsfelderEntities.Clear();
       entities.ForEach(e => ErgaenzungsfelderEntities.Add(e));
   }