DataStrid项目未在ObservableCollection更新时更新

时间:2014-09-11 07:57:21

标签: c# wpf data-binding datagrid

我有一个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 = m_dgErgaenzungsfelder.GetBindingExpression(ItemsControl.ItemsSourceProperty).UpdateSource();中的明确且未注释的ShowErgaenzungsfelder
  • UpdateSourceTrigger =的PropertyChanged
  • UpdateSourceTrigger =默认

我很感激任何意见。

1 个答案:

答案 0 :(得分:2)

这里有一些心灵调试。

服务层引发的事件未在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));
   }