WPF:向数据绑定集合添加元素(依赖属性)

时间:2009-05-10 16:47:16

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

我有这个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<ShoutBoxEntry>

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:0)

更改条目类型确实可以解决问题... 如果你想避免显式调用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/