CheckBox ListView SelectedValues ​​DependencyProperty Binding - PullRequest
1 голос
/ 08 января 2011

Я пишу пользовательский элемент управления, который представляет собой ListView, который имеет CheckBox для каждого элемента в ListView, чтобы указать, что элемент выбран. Я смог сделать это с помощью следующего XAML.

<ListView x:Class="CheckedListViewSample.CheckBoxListView"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          mc:Ignorable="d">
    <ListView.Style>
        <Style TargetType="{x:Type ListView}">
            <Setter Property="SelectionMode" Value="Multiple" />
            <Style.Resources>
                <Style TargetType="ListViewItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListViewItem">
                                <Border BorderThickness="{TemplateBinding Border.BorderThickness}"
                                        Padding="{TemplateBinding Control.Padding}"
                                        BorderBrush="{TemplateBinding Border.BorderBrush}"
                                        Background="{TemplateBinding Panel.Background}"
                                        SnapsToDevicePixels="True">
                                    <CheckBox IsChecked="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}">
                                        <CheckBox.Content>
                                            <ContentPresenter Content="{TemplateBinding ContentControl.Content}"
                                                              ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
                                                              HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
                                                              VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
                                                              SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
                                        </CheckBox.Content>
                                    </CheckBox>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Style.Resources>
        </Style>
    </ListView.Style>
</ListView>

Однако я пытаюсь попробовать еще одну функцию. ListView имеет свойство SelectedItems DependencyProperty, которое возвращает коллекцию проверенных элементов. Тем не менее, мне нужно реализовать SelectedValues ​​DependencyProperty. Я также реализую свойство SelectedValuesPath DependencyProperty. Используя SelectedValuesPath, я указываю путь, где находятся значения для каждого выбранного элемента. Поэтому, если мои элементы имеют свойство ID, я могу указать, используя свойство SelectedValuesPath «ID». Свойство SelectedValues ​​затем возвращает коллекцию значений ID. У меня это работает, также используя этот код в коде позади:

using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;

namespace CheckedListViewSample
{
    /// <summary>
    /// Interaction logic for CheckBoxListView.xaml
    /// </summary>
    public partial class CheckBoxListView : ListView
    {
        public static DependencyProperty SelectedValuesPathProperty =
            DependencyProperty.Register("SelectedValuesPath", 
            typeof(string),
            typeof(CheckBoxListView),
            new PropertyMetadata(string.Empty, null));

        public static DependencyProperty SelectedValuesProperty =
            DependencyProperty.Register("SelectedValues", 
            typeof(IList), 
            typeof(CheckBoxListView),
            new PropertyMetadata(new List<object>(), null));

        [Category("Appearance")]
        [Localizability(LocalizationCategory.NeverLocalize)]
        [Bindable(true)]
        public string SelectedValuesPath
        {
            get
            {
                return ((string)(base.GetValue(CheckBoxListView.SelectedValuesPathProperty)));
            }
            set
            {
                base.SetValue(CheckBoxListView.SelectedValuesPathProperty, value);
            }
        }

        [Bindable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Category("Appearance")]
        public IList SelectedValues
        {
            get
            {
                return ((IList)(base.GetValue(CheckBoxListView.SelectedValuesPathProperty)));
            }
            set
            {
                base.SetValue(CheckBoxListView.SelectedValuesPathProperty, value);
            }
        }

        public CheckBoxListView()
            : base()
        {
            InitializeComponent();
            base.SelectionChanged += new SelectionChangedEventHandler(CheckBoxListView_SelectionChanged);     
        }

        private void CheckBoxListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            List<object> values = new List<object>();

            foreach (var item in SelectedItems)
            {
                if (string.IsNullOrWhiteSpace(SelectedValuesPath))
                {
                    values.Add(item);
                }
                else
                {
                    try
                    {
                        values.Add(item.GetType().GetProperty(SelectedValuesPath).GetValue(item, null));
                    }
                    catch { }
                }
            }

            base.SetValue(CheckBoxListView.SelectedValuesProperty, values);

            e.Handled = true;
        }
    }
}

Моя проблема в том, что моя привязка работает только в одну сторону. У меня возникли проблемы при попытке выяснить, как реализовать мой SelectedValues ​​DependencyProperty, чтобы я мог привязать к нему коллекцию значений, и когда элемент управления загружен, CheckBoxes проверяются с элементами, значения которых соответствуют SelectedValues.

Я подумал об использовании события PropertyChangedCallBack, но не могу понять, как мне написать это для достижения своей цели.

Я также не уверен, как найти правильный ListViewItem, чтобы установить его в качестве выбранного.

И, наконец, если я смогу найти ListViewItem и установить для него значение Selected, не будет ли это запускать мое событие SelectionChanged каждый раз, когда я устанавливаю ListViewItem для выбора?

...