如何使自定义控件上的 DependencyProperty 接受 CollectionViewSource 绑定?

How to make a DependencyProperty on a Custom Control accept a CollectionViewSource Binding?

背景:

问题:

我无法(或不知道如何)在我的 CustomControl 上创建将绑定到 CollectionViewSource 和 update/trigger 的 DependencyProperty当 ColelctionViewSource 的 View 发生变化时(即当 Filtering 发生变化时)。

DependencyProperty 应该是什么类型才能绑定到 CollectionViewSource Object 类型显示绑定 CollectionViewSource 将作为 ListCollectionView 传递给我的 CustomControl DependencyProperty - 但 ListCollectionView 不提供事件(可见,即不 InternalCollectionChanged.

ItemsControl 派生为我的 CustomControlBaseClass 不是一个选项。 旁注 - 我不需要从 ItemsControl 派生来实现此功能:我将如何创建一个 CustomControl 具有 2 个接受 2 个不同 CollectionViewSources 的绑定( ItemsControl 不能这样做)?

代码:

CollectionViewSource "ClustersView"

DataGridItemsSource 绑定到 "ClustersView"(这很好用)

NavigatorControl: 这是我的CustomControl

代码:

<CollectionViewSource x:Key="ClustersView" 
                          Source="{Binding EventClusters, ElementName=me}" 
                          Filter="ClustersViewSource_Filter"></CollectionViewSource>

<DataGrid ItemsSource="{Binding Source={StaticResource ClustersView}}">

<LightMapperControls:NavigatorControl Clusters="{Binding Source={StaticResource ClustersView}}">
            </LightMapperControls:NavigatorControl>

 //The DP on NavigatorControl that I bind the CollectionViewSource to
public object Clusters
            {
                get { return (object)GetValue(ClustersProperty); }
                set { SetValue(ClustersProperty, value); }
            }
    // Using a DependencyProperty as the backing store for Clusters.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ClustersProperty =
        DependencyProperty.Register("Clusters", typeof(object), typeof(NavigatorControl), new PropertyMetadata(null, OnClustersChanged));

private static void OnClustersChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            ListCollectionView lcv = (ListCollectionView)e.NewValue;     //e.NewValue is of type ListCollectionView

            //lcv.Items     //no such property
            //lcv.CollectionChanged     //no such event
        }

解决办法是让WPF做所有的工作!我做了ClustersDependencyObject类型object ,然后添加 FrameworkPropertyMetadataOption.AffectsRender 以触发 OnRender 以在 Clusters 更改时重绘 canvas(即在 CollectionViewSource 上进行过滤)。 (重绘 canvas 的实际方法是从 OnRender 调用的 DrawClusters)。 DrawClusters 包含从 Clusters (object) 到 ICollectionView 的转换,我在 for..each 循环中列举了它以访问每个单独的 Cluster

感谢@PeterDuniho 提出的问题,这些问题迫使我重新审视我自以为知道的事情!

相关代码如下

    public object Clusters
    {
        get { return (object)GetValue(ClustersProperty); }
        set { SetValue(ClustersProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ClustersProperty =
        DependencyProperty.Register("Clusters", typeof(object), typeof(NavigatorControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));

private void DrawClusters(ref DrawingContext dc, ref double SquareWidth, ref double SquareHeight)
    {
        if (Clusters == null)
            return;
        if (ClustersVisibility == Visibility.Visible)
        {
            ICollectionView cv = (ICollectionView)Clusters;

            foreach (ClusterBase cluster in cv)
            {
                PathGeometry geometry = new PathGeometry();
                foreach (ClusterSquare square in cluster.Squares)
                {
                    geometry = Geometry.Combine(geometry, new RectangleGeometry(square.ToRect(SquareWidth, SquareHeight)), GeometryCombineMode.Union, null);
                }
                dc.DrawGeometry(clustersbrush, clusterspen, geometry);
            }
        }
    }