2017-04-08 84 views
1

我已經實現了自己的ObservableDictionary,因爲A)我不喜歡代碼,我看到其他人張貼和B)想要的做法。據我所知,一切工作正常,包括通知聽衆,但由於某種原因,我試圖用來顯示內容不會更新的ListView自定義Observable不更新UWP ListView

我的理解是,它使用INotifyCollectionChanged來監聽更改。就像完整性檢查一樣,我在頁面初始化時將一個偵聽器附加到CollectionChanged事件上,並且在添加項目時確實會觸發該事件,即使ListView未顯示任何內容。我知道我已經正確設置了XAML - 如果在將所有內容添加到字典後重新設置代碼隱藏ItemsSource,所有內容都會正確顯示;同樣,只要我更改二元字典.Add(...)的參數以適應單元素集合,即使沒有人工干預,用內置ObservableCollection(不接觸XAML)代替ObservableDictionary也可以很好地工作。

比較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); 
     } 
    } 
} 

就像我說,我看不出兩者之間有任何實質性差異。我是否錯過了某些明顯的東西,或者有什麼特別的東西來處理任何人都知道如何解決的觀察集合?

編輯:作爲參考,XAML中的元素與下面的行綁定;零索引行包含一個TextBlock,我用它來指示集合何時已完全填充。正如我上面所說的,只是簡單地將「庫」屬性的類型從ObservableDictionary<string, StorageFile>更改爲ObservableCollection<string>(和ObservableCollection<StorageFile>沒有什麼不同),可以在沒有我觸摸XAML的情況下正常工作。

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

你如何綁定到列表? xaml綁定代碼是什麼樣的? – Laith

+0

@Lithith將其添加到原始帖子。 –

回答

0

看你的源代碼,我注意到你的ObservableDictionaryBase<TKey, TValue>沒有實現IList<TValue>。你需要有一個索引器可用於ListView

不管綁定到ListView.ItemsSource需要實現INotifyCollectionChanged還是IList。當它收到字典中的更改通知時,它將嘗試通過索引器檢索更改(即page.Library[n])。

這最終會引導您執行一個類似於KeyedCollection<TKey, TValue>的實現,其中您具有有序元素的有序列表。

+0

完成了,謝謝!我假設'IEnumerable'就足夠了。現在我只需要做到這一點;內建的OrderedDictionary沒有一個通用的版本(並且沒有一個Nuget包支持.NETStandard)。至少C#公開'LinkedListNode'。 –