2012-05-05 11 views
2

添付ビュービヘイビアをCollectionViewSourceに追加して、XAMLのビューモデルでフィルタ述語プロパティを提供できるようにしようとしています。添付動作をCollectionViewSourceにどのように追加できますか?

XAMLは、次のようになります。

<DataGrid ItemsSource="{Binding}"> 
    <DataGrid.DataContext> 
     <CollectionViewSource Source="{Binding Path=Items}" 
       acb:CollectionViewSourceItemFilter.ItemFilter="{Binding Path=ItemFilter}" /> 
    </DataGrid.DataContext> 
</DataGrid> 

しかし、私はエラーを取得しています:

A 'Binding' cannot be set on the 'SetItemFilter' property of type 
'CollectionViewSource'. A 'Binding' can only be set on a DependencyProperty of a 
DependencyObject. 

CollectionViewSourceは、DependencyObjectのように見えます。私は何が間違っているのか分かりません。

次は、行動コードです:問題の行動のコードを投稿

public static class CollectionViewSourceItemFilter 
{ 
    /// <summary> 
    /// Gets the property value. 
    /// </summary> 
    public static Predicate<object> GetItemFilter(CollectionViewSource collectionViewSource) 
    { 
     return (Predicate<object>)collectionViewSource.GetValue(ItemFilter); 
    } 

    /// <summary> 
    /// Sets the property value. 
    /// </summary> 
    public static void SetItemFilter(CollectionViewSource collectionViewSource, Predicate<object> value) 
    { 
     collectionViewSource.SetValue(ItemFilter, value); 
    } 

    /// <summary> 
    /// The ItemFilter dependency property. 
    /// </summary> 
    public static readonly DependencyProperty ItemFilter = 
     DependencyProperty.RegisterAttached(
     "ItemFilter", 
     typeof(Predicate<object>), 
     typeof(ItemFilterBehavior), 
     new UIPropertyMetadata(null, OnItemFilterChanged)); 

    private static void OnItemFilterChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e) 
    { 
     CollectionViewSource collectionViewSource = depObj as CollectionViewSource; 
     if (collectionViewSource == null) 
      return; 

     if (!Equals(e.NewValue, e.OldValue)) 
     { 
      var newFilter = (Predicate<object>)e.NewValue; 

      // Remove any previous filter. 
      ItemFilterBehavior oldBehavior; 
      if (behaviors.TryGetValue(collectionViewSource, out oldBehavior)) 
      { 
       oldBehavior.Unregister(); 
       behaviors.Remove(collectionViewSource); 
      } 

      if (newFilter != null) 
       behaviors.Add(collectionViewSource, new ItemFilterBehavior(collectionViewSource, newFilter)); 
     } 
    } 

    private class ItemFilterBehavior 
    { 
     public ItemFilterBehavior(CollectionViewSource collectionViewSource, Predicate<object> filter) 
     { 
      _collectionViewSource = collectionViewSource; 
      _filter = filter; 
      _collectionViewSource.Filter += collectionViewSource_Filter; 
     } 

     void collectionViewSource_Filter(object sender, FilterEventArgs e) 
     { 
      e.Accepted = _filter(e.Item); 
     } 

     public void Unregister() 
     { 
      _collectionViewSource.Filter -= collectionViewSource_Filter; 
     } 

     private readonly CollectionViewSource _collectionViewSource; 
     private readonly Predicate<object> _filter; 
    } 

    private static readonly IDictionary<CollectionViewSource, ItemFilterBehavior> behaviors = new ConcurrentDictionary<CollectionViewSource, ItemFilterBehavior>(); 
} 
+0

これを試してください: 'public static readonly DependencyProperty ItemFilterProperty = ...' –

+1

あなたの質問を投稿していただきありがとうございます。それは、私がそこにいるのと同じ事実をやろうとしている人がそこにいることを私に気付かせました。 – jpierson

+0

@jpiersonポスト日付記念日upvote。 MVVMでCollectionViewSourceをフィルタリングすることに関するすべての議論で、この投稿はLOTSにもっと注意を払うと思います。 – TaterJuice

答えて

1

はそれを把握するために私を導きました。 My DependencyPropertyは、オーナータイプとしてCollectionViewSourceItemFilterの代わりにItemFilterBehaviorを使用しました。

関連する問題