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=默认
如有任何意见,我将不胜感激。
这里有一些心理调试。
服务层引发的事件没有在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));
}