我已经实现了自己的ObservableDictionary
,因为A)我对我看到的其他人发布的代码感到不满意,B)想要练习。据我所知,一切正常,包括通知听众,但由于某种原因,我试图用来显示内容的ListView
不会更新。
我的理解是它使用INotifyCollectionChanged
侦听更改。就像完整性检查一样,我在页面初始化时为CollectionChanged
事件添加了一个监听器,并且在我添加项目时会正确触发,即使ListView
没有显示任何内容。我知道我已经正确设置了XAML - 如果我在将所有内容添加到字典后重新设置代码隐藏中的ItemsSource
,一切都会正确显示;同样,只要我更改双元素字典ObservableDictionary
的参数,即使没有手动干预,用内置ObservableCollection
替换.Add(...)
(不接触XAML)也能很好地工作。适合单元素集合。
将my source code与ObservableCollection
进行比较,我能看到的唯一主要区别是它们包含添加对象的索引,但即使将其添加到我的代码中也不会改变任何内容。
要提取相关代码,我的(事实上有些过度设计)事件触发系统:
Tuple<bool, TValue> SendAddEvents(Func<bool> preTest, Func<Tuple<bool, TValue>> action, KeyValuePair<TKey, TValue> item) {
if (preTest.Invoke()) {
#if (SUPPORT_PROPERTYCHANGING_EVENT)
PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(nameof(Keys)));
PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(nameof(Values)));
PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(nameof(Count)));
#endif
OnAdding(item);
}
var result = action.Invoke();
if (result.Item1) {
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add,
item
));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Keys)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Values)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
OnAdd(item);
}
return result;
}
(据我所知),官方系统:
protected override void InsertItem(int index, T item)
{
CheckReentrancy();
base.InsertItem(index, item);
OnPropertyChanged(CountString);
OnPropertyChanged(IndexerName);
OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
}
private void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
}
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged != null)
{
using (BlockReentrancy())
{
CollectionChanged(this, e);
}
}
}
像我说的那样,我看不出两者之间有什么实质性的区别。我是否遗漏了一些明显的东西,或者是否有一些关于ListView
如何处理任何人都知道如何解决的可观察集合的特殊问题?
编辑:作为参考,XAML中的元素与以下行绑定;零索引行包含一个TextBlock
,我用它来指示集合何时完全填充。正如我上面所说的那样,只需将“库”属性的类型从ObservableDictionary<string, StorageFile>
更改为ObservableCollection<string>
(和ObservableCollection<StorageFile>
并没有什么不同),即使没有触及XAML,一切正常。< / p>
<ListView ItemsSource="{Binding Library, ElementName=page}" Grid.Row="1" />
答案 0 :(得分:0)
查看您的源代码,我发现您的ObservableDictionaryBase<TKey, TValue>
未实现IList<TValue>
。您需要为ListView
提供索引器。
ListView.ItemsSource
需要同时实施INotifyCollectionChanged
和IList
。当通知字典中的更改时,它将尝试通过索引器检索更改(即page.Library[n]
)。
这最终将引导您进行类似于KeyedCollection<TKey, TValue>
的实现,其中您有一个有序元素的有序列表。