【问题标题】:DataGrid Items not being updated on ObservableCollection changeDataGrid 项目未在 ObservableCollection 更改时更新
【发布时间】:2014-11-05 02:07:00
【问题描述】:

我有一个 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。这样做时,添加的实体将显示在网格中,删除的实体将被删除。但是,修改后的实体不会反映字段名称和 ErgaenzungsfeldType 的更改(这是唯一可以更改的属性)。
例如。更改列排序将触发网格更新并显示正确的值。

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

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

  • UpdateSourceTrigger=在ShowErgaenzungsfelder 中明确且未注释m_dgErgaenzungsfelder.GetBindingExpression(ItemsControl.ItemsSourceProperty).UpdateSource();
  • UpdateSourceTrigger=PropertyChanged
  • UpdateSourceTrigger=默认

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

【问题讨论】:

  • “显式”关键字不会告诉您自己更新数据源吗?你试过没有UpdateSourceTrigger这个属性吗?
  • 是的,这是我在 PropertyChanged 没有触发更新后的最后一次尝试,但它对 ItemsControl.ItemsSourceProperty 不起作用(这是正确的吗?)

标签: c# wpf data-binding datagrid


【解决方案1】:

这里有一些心理调试。

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

要对此进行测试,您需要将更新发送到 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));
   }

【讨论】:

  • Doh,我想提一下,但忘记了:/事件正在使用CurrentDispatcher 在 UI 线程上分派。虽然可能是一个很好的猜测
  • 哦,好吧 :) 作为腰带和大括号的事情,您可以在 ShowErgaenzungsfelderEntities 方法中使用 NotifyPropertyChanged("ErgaenzungsfelderEntities") 看看是否有帮助..
  • 我现在在ErgaenzungsfelderView 上实现了INotifyPropertyChanged,并在ShowErgaenzungsfelder 的末尾调用OnPropertyChanged("ErgaenzungsfelderEntities");。 ItemsSource 现在是ItemsSource="{Binding Path=ErgaenzungsfelderEntities, UpdateSourceTrigger=PropertyChanged, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, Mode=OneWay}"。不幸的是,行为仍然相同
  • 为了简化,我将绑定更改为 ItemsSource="{Binding Path=ErgaenzungsfelderEntities, Mode=OneWay}"。如果网格是只读的(看起来像),我会尝试 TwoWay 看看是否有帮助。
  • 是的,网格是只读的。由于 ErgaenzungsfelderEntities 的私有设置器,TwoWay 绑定引发异常(更改它以进行测试没有效果)。删除其他属性的效果与之前相同。
猜你喜欢
  • 2018-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多