Wpf 复选框ListView SelectedValues DependencyProperty绑定

Wpf 复选框ListView SelectedValues DependencyProperty绑定,wpf,listview,checkbox,listviewitem,selectedvalue,Wpf,Listview,Checkbox,Listviewitem,Selectedvalue,我正在编写一个自定义控件,它是一个ListView,在ListView中的每个项目上都有一个复选框,以指示该项目已被选中。我可以使用下面的XAML来实现这一点 <ListView x:Class="CheckedListViewSample.CheckBoxListView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schema

我正在编写一个自定义控件,它是一个ListView,在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;
        }
    }
}
使用System.Windows;
使用System.Windows.Controls;
使用系统组件模型;
使用系统集合;
使用System.Collections.Generic;
命名空间CheckedListViewSample
{
/// 
///CheckBoxListView.xaml的交互逻辑
/// 
公共部分类CheckBoxListView:ListView
{
公共静态从属属性SelectedValue属性=
DependencyProperty.Register(“SelectedValuesPath”,
类型(字符串),
类型(复选框列表视图),
新的PropertyMetadata(string.Empty,null));
公共静态依赖属性Selected Value属性=
DependencyProperty.Register(“SelectedValues”,
类型(IList),
类型(复选框列表视图),
新的PropertyMetadata(新列表(),null));
[类别(“外观”)]
[可本地化性(本地化类别:NeverLocalize)]
[可装订(真实)]
公共字符串SelectedValuesPath
{
得到
{
返回((字符串)(base.GetValue(CheckBoxListView.SelectedValuesPathProperty));
}
设置
{
base.SetValue(CheckBoxListView.SelectedValuesPath属性,值);
}
}
[可装订(真实)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[类别(“外观”)]
公共IList SelectedValues
{
得到
{
返回((IList)(base.GetValue(CheckBoxListView.SelectedValuesPathProperty));
}
设置
{
base.SetValue(CheckBoxListView.SelectedValuesPath属性,值);
}
}
公共CheckBoxListView()
:base()
{
初始化组件();
base.SelectionChanged+=新的SelectionChangedEventHandler(复选框列表视图\u SelectionChanged);
}
private void CheckBoxListView\u SelectionChanged(对象发送者,SelectionChangedEventArgs e)
{
列表值=新列表();
foreach(SelectedItems中的变量项)
{
if(string.IsNullOrWhiteSpace(SelectedValuesPath))
{
增加(项目);
}
其他的
{
尝试
{
添加(item.GetType().GetProperty(SelectedValuesPath).GetValue(item,null));
}
捕获{}
}
}
base.SetValue(CheckBoxListView.SelectedValuesProperty,values);
e、 已处理=正确;
}
}
}
我的问题是,我的绑定现在只能以一种方式工作。我在试图弄清楚如何实现SelectedValues DependencyProperty以将一组值绑定到它时遇到了问题,当加载控件时,复选框中的项的值与SelectedValues对应

我曾考虑过使用PropertyChangedCallBack事件,但不太清楚如何编写它来实现我的目标

我也不确定如何找到正确的ListViewItem将其设置为选中


最后,如果我能找到ListViewItem并将其设置为Selected,那么每次我设置ListViewItem为Selected时不会触发我的SelectionChanged事件吗

浏览以下链接


浏览以下链接


我可以使用一个附加属性来实现这一点。差不多了。我为ListBox(也适用于ListView)创建了一个名为SelectedValues的附加属性。每样东西都能很好地工作。加载控件时,绑定到my属性的一个集合中存储的ID会正确选择ListView控件中的项。当我在控件中进行更改时,绑定到附加属性的源将更新。但是,当我从后面的代码更新源代码时,我的控件仍然不会自动更新。我不确定我做错了什么。我可以用一个附加的属性使它工作。差不多了。我为ListBox(也适用于ListView)创建了一个名为SelectedValues的附加属性。每样东西都能很好地工作。加载控件时,绑定到my属性的一个集合中存储的ID会正确选择ListView控件中的项。当我在控件中进行更改时,绑定到附加属性的源将更新。然而,当我从后面的代码更新源代码时,我的控件仍然不会自动更新