2014-10-28 66 views
5

通過綁定同步兩組數據的最佳方式是什麼?現在雙向收集綁定同步/鎖

Target = Custom Setters - raises custom events whenever something changed 
Source = ObservableCollection - raises events whenever collection changed 

我的問題是,當我收到從一個集合(例如Source.CollectionChanged事件)的更新,我需要調用自定義TargetSetters,而忽略它源於我的更新被稱爲事件。

還有另一種方式,當Target自定義事件被觸發時,我需要更新源,但忽略CollectionChanged事件。

目前,我正在保持對我的處理程序的引用,並在更新任何集合之前刪除它。例如

private void ObservableCollection_OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) 
{ 
    CustomObject.SelectionChanged -= CustomObject_SelectionChanged; 
    // Do change logic and update Custom Object.... 
    CustomObject.SelectionChanged += CustomObject_SelectionChanged; 
} 

void CustomObject_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    ObservableCollection.CollectionChanged -= ObservableCollection_OnCollectionChanged; 
    // Do change logic and update ObservableCollection... 
    ObservableCollection.CollectionChanged += ObservableCollection_OnCollectionChanged; 
} 

我看到您可以使用if語句來檢查更新是否來自源代碼,以及它們是否忽略它們。例如

private void ObservableCollection_OnCollectionChanged2(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) 
{ 
    if (BindingTargetUpdating) return; 
    BindingSourceUpdating = true; 
    // Do change logic and update Custom Object.... 
    BindingSourceUpdating = false; 
} 

void CustomObject_SelectionChanged2(object sender, SelectionChangedEventArgs e) 
{ 
    if (BindingSourceUpdating) return; 
    BindingTargetUpdating = true; 
    // Do change logic and update ObservableCollection... 
    BindingTargetUpdating = false; 
} 

後谷歌+ SO搜索無功而返,我想看看別人是如何做,並且有很簡單的東西,我在這裏失蹤,解決這個問題呢? (我知道這些例子不是線程安全的)

如果不是,那麼首選方法是什麼?刪除和附加處理程序,或設置布爾標誌?什麼是更高性能(是的,我知道這是不太可能造成瓶頸,但出於好奇)

我問的原因是因爲,目前我正在實施附加行爲,併爲每個行爲,我創建2套字典其中每個對象的處理程序都有引用,因爲狀態必須傳遞。

我似乎無法找到.NET Binding類的綁定機制的源代碼,看看MS如何實現它。如果任何人有一個鏈接到那些將不勝感激。

+0

對不起,我可能會丟失一些東西,但是爲什麼您的設計要求您忽略每次發生更改時發生的一些事件?我無法弄清楚你想完成什麼。你能否說出你想解決的問題? – furkle 2014-10-28 23:51:02

+0

因爲如果您訂閱雙方,您將收到雙方的通知。造成無限循環。例如。Customibject引發事件發生變化,我的處理程序被調用並更改綁定的集合,這反過來引發了更改的事件,所以我的集合更改了處理程序被調用,其中編輯了自定義對象。這會再次引發事件,並且你處於循環中 – 2014-10-29 00:22:36

+2

對,我說的是設計你的程序的方式必須有意地阻止它進入無限循環,這是一個相當大的代碼味道。是否有理由不只是通過INotifyPropertyChanged處理對集合的更改,還是我誤解了你的目的? – furkle 2014-10-29 00:24:58

回答

3

您正在使用的機制 - 具有跟蹤何時發生更新以及阻止它的布爾值是最常見的方法。

就個人而言,我更喜歡將該邏輯包裝到一個實用程序IDisposable中。這樣可以更容易地保證你總是能夠自己清理。

您可以使用此實用程序會看起來像:

class Guard : IDisposable 
{ 
    readonly Func<bool> getter; 
    readonly Action<bool> setter; 

    readonly bool acquired = false; 
    public Guard(Func<bool> getter, Action<bool> setter) 
    { 
     this.getter = getter; 
     this.setter = setter; 

     if (this.getter() == false) 
     { 
      this.setter(true); 
      this.acquired = true; 
     } 
    } 

    public bool Acquired { get { return this.acquired; } } 

    void IDisposable.Dispose() 
    { 
     if (acquired) 
     { 
      this.setter(false); 
     } 
    } 
} 

然後你可以寫:

private void ObservableCollection_OnCollectionChanged2(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) 
{ 
    using(var guard = new Guard(() => BindingTargetUpdating, v => BindingTargetUpdating = value)) 
    { 
     if (guard.Acquired) 
     { 
      // Do change logic and update Custom Object.... 
     } 
    } 
} 

這不一定是任何短 - 它可能是更長的時間來寫,但如果發生異常,將確保您可以釋放塊。如果您經常使用它,您總是可以繼承Guard以減少使用量。