【问题标题】:Getting WPF to update a bound list of DataTables让 WPF 更新数据表的绑定列表
【发布时间】:2013-02-06 11:06:26
【问题描述】:

我有一个绑定到Dictionary<string, DataTable> 的选项卡式小部件。选项卡名称绑定到字典Keys,选项卡内容绑定到DataTables。这一切都很好,但在构建后的某个未指定的点,所有表都被重建为一个更大更复杂的表。我的问题是如何提供更改通知以便 WPF 正确更新表格?

这似乎是一件很明显的事情,我想知道我是否遗漏了什么,或者我真的需要使用可观察的字典构造或带有更改通知的自定义 DataTable 包装器?

到目前为止我尝试过的解决方案:

  • 使用ObservableCollection< KeyValuePair<string, DataTable> 并添加或删除条目。这实际上可以正常工作,但最终会导致在需要更新表格时标签消失和重新出现的视觉效果不佳

  • 我显然可以使用代码隐藏来破解它,但如果可能的话,我想避免这种情况。

这里是 XAML

<TabControl ItemsSource="{Binding StringToDataTableDictionary}" >
  <TabControl.ItemTemplate>
    <DataTemplate>
      <Label Content="{Binding Key}" />
    </DataTemplate>
  </TabControl.ItemTemplate>
  <TabControl.ContentTemplate>
    <DataTemplate>
      <igDP:XamDataGrid DataSource="{Binding Path=Value}"
    </DataTemplate>
  </TabControl.ContentTemplate>
</TabControl>

【问题讨论】:

    标签: c# wpf binding datatable


    【解决方案1】:

    因此,归根结底,您需要一个实现INotifyCollectionChangedIEnumerable 的类(例如ObservableCollectionICollectionView)。当然,你也可以自己编一个。主要的是你在你的类中实现了这两个接口,然后当集合发生变化时调用CollectionChanged

    一个简单的例子:

    class MyObservableDictionary<T, U> : INotifyCollectionChanged, IEnumerable
    {
        Dictionary<T, U> items = new Dictionary<T,U>();
    
        public void Add(T key, U value)
        {
            this.items.Add(key, value);
    
            // Update any listeners
            if (CollectionChanged != null)
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }
    
        // This is from implementing INotifyCollectionChanged
        public event NotifyCollectionChangedEventHandler CollectionChanged;
    
        // This is from implementing IEnumerable
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            // Dump the entire collection into a 'yield return'. C# will automatically
            // build an enumerator class from it.
            foreach (KeyValuePair<T, U> item in items)
                yield return item;
        }
    }
    

    如您所见,当我添加一个项目时,我确保CollectionChanged 不为空(也就是说,有人正在监视这个类的集合更改),然后我调用它。这会提示监控对象调用GetEnumerator。在GetEnumerator 函数中,我只为每个项目执行一个操作并“返回”每个项目(它告诉 c# 自动构建一个枚举器,因此我不必自己做)。

    XAML:

    <ListBox ItemsSource="{Binding Items}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Label Content="{Binding Key}" FontWeight="Bold"/>
                    <Label Content="{Binding Value}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    【讨论】:

    • 是的,我明白你在说什么,但这并不能解决我的问题,因为我的集合实际上并没有改变,只是集合中的 DataTable。
    【解决方案2】:

    最后,没有收集通知机制解决了我的问题。我猜这是因为在幕后,WPF 持有对 DataTable 的引用,这就是需要提供更改通知的引用。我意识到我可以删除该表并将其重新添加到集合中,但这会导致 GUI 速度过慢。因此,我构建了一个提供更改通知的 DataTable 包装器,请参见此处:

    public class DataTableWithNotification : INotifyPropertyChanged
    {
        private DataTable _theTable = new DataTable();
    
        public DataTableWithNotification()
        {
        }
    
        public DataTableWithNotification(DataTable dt)
        {
            _theTable = dt;
        }
    
        public DataTable Table
        {
            get { return _theTable; }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        public void ChangeTableAndNotify(DataTable newTable)
        {
            _theTable = newTable;
    
            OnPropertyChanged("Table");
        }
    
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-08-06
      • 1970-01-01
      • 2017-11-26
      • 1970-01-01
      • 2010-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多