【问题标题】:WPF: Adding an element to a databound Collection (a Dependency Property)WPF:将元素添加到数据绑定集合(依赖属性)
【发布时间】:2009-05-10 16:47:16
【问题描述】:

我有这个DependencyProperty,它拥有一个具有集合属性的实体 (ShoutBox.Entities):

public static readonly DependencyProperty ShoutBoxProperty = DependencyProperty.Register("ShoutBox",typeof (ShoutBox),typeof (ShoutBoxViewerControl));

public ShoutBox ShoutBox
{
    get { return (ShoutBox) GetValue(ShoutBoxProperty); }
    set { SetValue(ShoutBoxProperty, value); }
}

它被绑定在xaml 中,如下所示:

<ItemsControl ItemsSource="{Binding ShoutBox.Entries}">
.
.
</ItemsControl>

当我第一次绑定它时,它按预期工作,但有时我需要将项目添加到集合中(使用同一控件中的方法),如下所示:

public void AddNewEntry(ShoutBoxEntry newEntry)
{
    Dispatcher.Invoke(new Action(() =>{
        ShoutBox.Entries.Add(newEntry); //Adding directly the the Dependency property
    }));
}

问题是当我使用上述方法添加一个新元素时,该项目没有显示在ItemsControl中。


我的问题是,为什么我添加的新元素没有显示在 ItemsControl 中?


[编辑]

Entries (ShoutBox.Entries) 的类型为 List&lt;ShoutBoxEntry&gt;

【问题讨论】:

    标签: c# wpf data-binding xaml dependency-properties


    【解决方案1】:

    参赛作品的类型是什么?它要么需要 ObservableCollection,要么实现 ICollectionChanged。否则绑定不知道添加了新项目。

    【讨论】:

    • 这就是问题所在。将 List 更改为 ObservableCollection,它应该可以工作。 msdn.microsoft.com/en-us/library/ms668604.aspx
    • 为了获取添加和删除项目,Collection 需要实现 ICollectionChanged,而不是 INotifyPropertyChanged。
    【解决方案2】:

    更改条目类型确实应该可以解决问题... 如果您想避免显式调用 Dispatcher.Invoke,我编写了一个集合,该集合在创建集合的线程上引发 CollectionChanged 和 PropertyChanged 事件:

    public class AsyncObservableCollection<T> : ObservableCollection<T>
    {
        private SynchronizationContext _synchronizationContext = SynchronizationContext.Current;
    
        public AsyncObservableCollection()
        {
        }
    
        public AsyncObservableCollection(IEnumerable<T> list)
            : base(list)
        {
        }
    
        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            if (SynchronizationContext.Current == _synchronizationContext)
            {
                // Execute the CollectionChanged event on the current thread
                RaiseCollectionChanged(e);
            }
            else
            {
                // Post the CollectionChanged event on the creator thread
                _synchronizationContext.Post(RaiseCollectionChanged, e);
            }
        }
    
        private void RaiseCollectionChanged(object param)
        {
            // We are in the creator thread, call the base implementation directly
            base.OnCollectionChanged((NotifyCollectionChangedEventArgs)param);
        }
    
        protected override void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (SynchronizationContext.Current == _synchronizationContext)
            {
                // Execute the PropertyChanged event on the current thread
                RaisePropertyChanged(e);
            }
            else
            {
                // Post the PropertyChanged event on the creator thread
                _synchronizationContext.Post(RaisePropertyChanged, e);
            }
        }
    
        private void RaisePropertyChanged(object param)
        {
            // We are in the creator thread, call the base implementation directly
            base.OnPropertyChanged((PropertyChangedEventArgs)param);
        }
    }
    

    更多细节可以在这里找到: http://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-26
      • 2020-12-22
      • 1970-01-01
      • 2012-11-08
      • 2010-10-09
      • 2017-04-01
      • 2018-01-23
      • 2014-08-31
      相关资源
      最近更新 更多