2010-11-09 19 views
1

我正在使用WPF,並嘗試遵循MVVM模式。我們的團隊已經決定使用Xceed DataGrid控件,並且我很難將其融入MVVM模式。WPF,如何在看類型描述符時正確解除處理程序

我必須滿足的一個要求是我需要知道用戶何時更改網格上的列過濾器。我知道最新版本的DataGrid控件有一個事件引發了這個,但不幸的是,我不得不使用該控件的舊版本。我找到了this後。它說我需要將INotifyCollectionChanged處理程序掛接到每個可能的過濾器列表。這是有效的,但它也表示,當網格的行源發生更改時,我需要解除處理程序的綁定。

我能得到它時,我明確地設置在頁面的代碼隱藏的行源工作(在我的模型視圖第一次嘗試使用直接引用視圖喘氣!

我遇到的第一個問題是如何在代碼後面或ViewModel中沒有邏輯的情況下做到這一點。我的解決辦法是延長DataGridControl類,並添加以下代碼:

private IDictionary<string, IList> _GridFilters = null; 
    public MyDataGridControl() : base() 
    { 
     TypeDescriptor.GetProperties(typeof(MyDataGridControl))["ItemsSource"].AddValueChanged(this, new EventHandler(ItemsSourceChanged)); 
    } 

    void ItemsSourceChanged(object sender, EventArgs e) 
    { 
     UnsetGridFilterChangedEvent(); 
     SetGridFilterChangedEvent(); 
    } 

    public void SetGridFilterChangedEvent() 
    { 
     if (this.ItemsSource == null) 
      return; 

     DataGridCollectionView dataGridCollectionView = (DataGridCollectionView)this.ItemsSource; 

     _GridFilters = dataGridCollectionView.AutoFilterValues; 

     foreach (IList autofilterValues in _GridFilters.Values) 
     { 
      ((INotifyCollectionChanged)autofilterValues).CollectionChanged += FilterChanged; 
     } 
    } 

    /*TODO: Possible memory leak*/ 
    public void UnsetGridFilterChangedEvent() 
    { 
     if (_GridFilters == null) 
      return; 

     foreach (IList autofilterValues in _GridFilters.Values) 
     { 
      INotifyCollectionChanged notifyCollectionChanged = autofilterValues as INotifyCollectionChanged; 

      notifyCollectionChanged.CollectionChanged -= FilterChanged; 
     } 

     _GridFilters = null; 
    } 

這導致我的下一個問題;我很確定,在調用ItemsSourceChanged方法時,AutoFilterValues的集合已經更改,所以我無法有效地解除處理程序。

我是否有權利承擔這一點?任何人都可以想到一個更好的方式來管理這些處理程序,同時仍然允許我將這個功能封裝在擴展類中?

對不起有關帖子的長度,並預先感謝您的幫助!

-Funger

回答

0

你是正確AutoFilterValues將在這一點上已經改變了,所以你會脫鉤的錯誤處理,導致內存泄漏。

該解決方案非常簡單。你在做什麼,但使用List<IList>而不只是引用AutoFilterValues的:

private List<IList> _GridFilters; 

,並使用ToList()讓你在設置處理程序的過濾器的副本:

_GridFilters = dataGridCollectionView.AutoFilterValues.Values.ToList(); 

由於_GridFilters現在是List<IList>,你也必須改變循環:

foreach(IList autofilterValues in _GridFilters) 
    ... 

這部作品的原因是舊網絡的實際列表過濾器列表被複制到_GridFilters中,而不是簡單地引用AutoFilterValues屬性。

這是一個很好的通用技術,適用於許多情況。

+0

謝謝你的快速幫助! – BigFunger 2010-11-10 16:05:00