2016-09-22 55 views
0

我有一個使用受管UWP行爲SDK的UWP應用程序。 我寫了一個自定義行爲,它有兩個依賴屬性,其中之一是一個ObservableCollection。Xaml行爲DP未更新

每當我更新集合中的項目時,我確保爲集合調用PropertyChanged。

但是,依賴項屬性未被更新。

我的代碼:

<trigger:CustomBehavior ItemIndex="{x:Bind ItemIndex}" 
    Presences="{Binding ElementName=Box, 
     Path=DataContext.CustomCollection, 
      UpdateSourceTrigger=PropertyChanged, Converter={StaticResource TestConverter}}" /> 

我TestConverter讓我發現,當我更新集合中的一個項目,該updatesource觸發工作。但是,我的行爲中的依賴項屬性不會觸發Changed事件。當我更改整個自定義集合時,更新DP,當我只更改一個項目時,它不是。

迄今爲止的研究表明,DependencyObject.SetValue只是檢查對象是否已經改變,如果一個項目發生了變化,它會認爲該集合根本沒有改變?這是真的嗎?如果是這樣,我該如何克服這一點?

感謝

+0

首先說明:「當我更新集合中的項目時,更新源觸發器正在工作」是一種常見的誤解。在單向綁定中設置「UpdateSourceTrigger = PropertyChanged」不起作用,它只控制目標更改時更新綁定源的方式,即僅在雙向綁定或單向源綁定中有效。也就是說,更新集合中的項目然後引發一個PropertyChanged事件也沒有效果,因爲集合*實例*沒有更改,而且PropertyChanged事件被靜默地忽略。 – Clemens

+0

要麼替換整個集合,要麼在Presences屬性的PropertyChangedCallback中爲'INotifyCollectionChanged.CollectionChanged'事件註冊處理程序。 – Clemens

+0

美麗。你可以發佈這個答案,以便我可以接受嗎? – WJM

回答

2

一個集合類型依賴項屬性通常應被宣佈爲最基本的集合類型,IEnumerable。通過這種方式,您可以爲屬性指定各種實際的集合類型,包括實施INotifyCollectionChanged的集合類型,如ObservableCollection<T>

您將在運行時檢查集合類型是否實際實現接口,並可能爲CollectionChanged事件附加和分離處理程序方法。

public class CustomBehavior : ... 
{ 
    public static readonly DependencyProperty PresencesProperty = 
     DependencyProperty.Register(
      "Presences", typeof(IEnumerable), typeof(CustomBehavior), 
      new PropertyMetadata(null, 
       (o, e) => ((CustomBehavior)o).OnPresencesPropertyChanged(e))); 

    private void OnPresencesPropertyChanged(DependencyPropertyChangedEventArgs e) 
    { 
     var oldCollectionChanged = e.OldValue as INotifyCollectionChanged; 
     var newCollectionChanged = e.NewValue as INotifyCollectionChanged; 

     if (oldCollectionChanged != null) 
     { 
      oldCollectionChanged.CollectionChanged -= OnPresencesCollectionChanged; 
     } 

     if (newCollectionChanged != null) 
     { 
      newCollectionChanged.CollectionChanged += OnPresencesCollectionChanged; 
      // in addition to adding a CollectionChanged handler, any 
      // already existing collection elements should be processed here 
     } 
    } 

    private void OnPresencesCollectionChanged(
     object sender, NotifyCollectionChangedEventArgs e) 
    { 
     // handle collection changes here 
    } 
}