1

項目が選択されていることを示すために、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>

ただし、もう 1 つの機能を試しています。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 を実装して値のコレクションをバインドできるようにする方法を見つけようとして問題が発生しました。コントロールが読み込まれると、SelectedValues に対応する値を持つ項目で CheckBox がチェックされます。

PropertyChangedCallBack イベントの使用を検討しましたが、目標を達成するためにそれをどのように記述できるかがよくわかりません。

また、正しい ListViewItem を見つけて Selected として設定する方法もわかりません。

そして最後に、ListViewItem を見つけて Selected に設定できた場合、ListViewItem を Selected に設定するたびに SelectionChanged イベントが発生しませんか?

4