2017-04-08 10 views
1

A) 다른 사람들이 게시 한 코드에 만족스럽지 않고 B) 연습을 원했기 때문에 자신의 ObservableDictionary을 구현했습니다. 내가 알 수있는 한, 리스너에게 알리는 것을 포함하여 모든 것이 올바르게 작동하지만, 어떤 이유로 든 ListView은 내용을 표시하는 데 사용하려고 시도하지만 업데이트되지 않습니다.사용자 지정 Observable이 UWP를 업데이트하지 않음 ListView

내 이해는 INotifyCollectionChanged을 사용하여 변경 사항을 수신합니다. 온전한 체크와 마찬가지로, 페이지 초기화시 CollectionChanged 이벤트에 리스너를 연결했는데 항목을 추가 할 때 올바르게 표시되지만 ListView에는 아무 것도 표시되지 않습니다. XAML을 올바르게 설정했음을 알고 있습니다. 사전에 모든 것을 추가 한 후 코드 숨김에서 ItemsSource을 다시 설정하면 모든 것이 올바르게 표시됩니다. 마찬가지로 ObservableDictionary을 기본 제공 ObservableCollection (XAML을 건드리지 않음)으로 바꾸면 두 요소 사전 .Add(...)의 매개 변수가 단일 요소 컬렉션 1에 맞게 변경되는 한 수동 개입 없이도 완벽하게 작동합니다.

ObservableCollection의 코드와 비교하면, 내가 볼 수있는 유일한 차이점은 추가 된 개체의 인덱스가 포함되어 있지만 코드를 추가해도 아무 것도 변경되지 않는다는 것입니다. I처럼

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

: (지금까지 내가 말할 수있는)

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; 
} 

그리고, 공식 시스템 :

내 (일반적으로 인정 하듯이 다소 overdesigned) 이벤트 트리거 시스템, 관련 코드를 추출하려면 말했다, 나는이 둘 사이에 어떤 실질적인 차이도 볼 수 없다. 나는 명백한 것을 놓치고 있는가, 아니면 아무렇게나 작동하는 방법을 알고있는 관찰 가능한 컬렉션을 처리하는 방법에 대해 특이한 무언가가 있는가?

편집 : 참조를 위해 XAML의 요소는 다음 줄로 바인딩됩니다. 제로 인덱스 행에는 컬렉션이 완전히 채워 졌음을 나타 내기 위해 사용하는 TextBlock이 포함되어 있습니다. 위에서 말했듯이 단순히 "Library"속성의 유형을 ObservableDictionary<string, StorageFile>에서 ObservableCollection<string> (그리고 ObservableCollection<StorageFile>도 마찬가지입니다)으로 변경하면 XAML을 건드리지 않고도 모든 것이 작동합니다.

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

목록에 어떻게 바인딩하고 있습니까? xaml 바인딩 코드는 어떻게 생겼습니까? – Laith

+0

@Laith 원래 게시물에 추가했습니다. –

답변

0

는 소스 코드를 보면, 당신의 ObservableDictionaryBase<TKey, TValue>IList<TValue>를 구현하지 않습니다 나타났습니다. ListView에 사용할 수있는 인덱서가 있어야합니다.

ListView.ItemsSource에 바인딩 된 것은 INotifyCollectionChangedIList을 모두 구현해야합니다. 사전에 변경 사항이 통보되면 인덱서를 통해 변경 내용을 검색하려고 시도합니다 (예 : page.Library[n]).

그러면 키순 요소의 정렬 된 목록이있는 KeyedCollection<TKey, TValue>과 유사한 구현으로 연결됩니다.

+0

그게 다 됐어, 고마워! 나는'IEnumerable'만으로 충분하다고 가정했다. 이제 그 일을해야합니다. OrderedDictionary에는 일반 버전이 없으며 (.NETStandard를 지원하는 Nuget 패키지는 없음) 수치스러운 일입니다. 최소한 C#은'LinkedListNode'를 노출합니다. –