自定义 Observable 不更新 UWP ListView

Custom Observable not updating UWP ListView

我实现了自己的 ObservableDictionary,因为 A) 我对看到其他人发布的代码不满意,并且 B) 想要实践。据我所知,一切正常,包括通知听众,但由于某种原因,我试图用来显示内容的 ListView 没有更新。

我的理解是它使用INotifyCollectionChanged监听变化。就像完整性检查一样,我在页面初始化时为 CollectionChanged 事件附加了一个侦听器,当我添加项目时它会正确触发,即使 ListView 没有显示任何内容。我知道我已经正确设置了 XAML——如果我在将所有内容添加到字典后在代码隐藏中重新设置 ItemsSource,所有内容都会正确显示;同样,将 ObservableDictionary 替换为内置 ObservableCollection(不触及 XAML)即使没有手动干预也能很好地工作,只要我更改二元字典的参数 .Add(...)适合单元素集合one.

my source code to that for the 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 ,我用它来指示集合何时已完全填充。不过,正如我上面所说,只需将 "Library" 属性 的类型从 ObservableDictionary<string, StorageFile> 更改为 ObservableCollection<string>(并且 ObservableCollection<StorageFile> 没有什么不同)就可以使一切正常工作而无需我触摸 XAML.

<ListView ItemsSource="{Binding Library, ElementName=page}" Grid.Row="1" />

查看您的源代码,我注意到您的 ObservableDictionaryBase<TKey, TValue> 没有实现 IList<TValue>。您需要有一个可用于 ListView 的索引器。

绑定到 ListView.ItemsSource 的任何内容都需要同时实现 INotifyCollectionChangedIList。当它收到字典中更改的通知时,它将尝试通过索引器(即 page.Library[n])检索更改。

这最终会引导您实现类似于 KeyedCollection<TKey, TValue> 的实现,其中您有一个有序的键控元素列表。