自定义Observable不更新UWP ListView

时间:2017-04-08 22:03:12

标签: c# uwp observablecollection inotifycollectionchanged

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

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

my source codeObservableCollection进行比较,我能看到的唯一主要区别是它们包含添加对象的索引,但即使将其添加到我的代码中也不会改变任何内容。

要提取相关代码,我的(事实上有些过度设计)事件触发系统:

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" />

1 个答案:

答案 0 :(得分:0)

查看您的源代码,我发现您的ObservableDictionaryBase<TKey, TValue>未实现IList<TValue>。您需要为ListView提供索引器。

ListView.ItemsSource需要同时实施INotifyCollectionChangedIList。当通知字典中的更改时,它将尝试通过索引器检索更改(即page.Library[n])。

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