Как заставить DependencyProperty в пользовательском элементе управления принимать привязку CollectionViewSource? - PullRequest
0 голосов
/ 26 сентября 2019

Фон:

  • Я могу создать CollectionViewSource в XAML, получая данные из ObservableCollection в окне.
  • Привязка CollectionViewSource к DataGrid ведет себя точно так, как ожидалось (ItemsSource="{Binding Source={StaticResource ClustersView}}")
  • Фильтрация CollectionViewSource работает нормально.
  • Мой CustomControl работает нормально (по крайней мере, все остальныеПривязки и функциональность)

Проблема:

Я не могу (или не знаю, как) создать DependencyProperty на моем CustomControl, который будет привязываться к CollectionViewSource и обновляться / запускаться при изменении вида ColelctionViewSource (т. Е., Например, при изменении фильтрации).

Какой тип должен быть DependencyProperty, чтобы я мог связываться с типом CollectionViewSource? Object, показывает, что предел CollectionViewSource будет передан как ListCollectionView моемуCustomControl DependencyProperty - но ListCollectionView не предоставляет событие (видимое, т.е. не Internal) для CollectionChanged.

Вывод ItemsControl в качестве BaseClass длямой CustomControl не вариант. Дополнительный комментарий - мне не нужно извлекать из ItemsControl для достижения этой функции: Как бы я создал CustomControl с 2 привязками, которые принимают 2 разных CollectionViewSources (ItemsControl не сможетсделать это)?

Код:

CollectionViewSource "ClustersView"

DataGrid: ItemsSource привязан к "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
        }

1 Ответ

0 голосов
/ 26 сентября 2019

Решение состоит в том, чтобы позволить WPF делать всю работу! Я сделал Clusters DependencyObject типа object, затем добавил FrameworkPropertyMetadataOption.AffectsRender, чтобы вызвать OnRender, чтобы перерисоватьхолст всякий раз, когда Clusters изменяется (т. е. фильтрация происходит в CollectionViewSource).(Фактический метод для перерисовки холста DrawClusters вызывается из OnRender).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);
            }
        }
    }
...