WPF中继承ItemsControl子类控件数据模板获取选中属性

需求场景

列表类控件,如 ListBox、ListView、DataGrid等。显示的行数据中,部分内容依靠选中时触发控制,例如选中行时行记录复选,部分列内容控制显隐。

案例源码以ListView 为例。

Xaml 部分

xaml 复制代码
<ListView ItemsSource="{Binding MyPropertys}" IsManipulationEnabled="False">
    <ListView.View>
        <GridView>
            <!--该列用于自定义行逻辑-->
            <GridViewColumn Header="操作列" >
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <!--该列用于自定义行逻辑-->
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="内容列" DisplayMemberBinding="{Binding MyProperty}"/>
            <GridViewColumn Header="内容列" DisplayMemberBinding="{Binding MyProperty1}"/>
            <GridViewColumn Header="内容列" DisplayMemberBinding="{Binding MyProperty2}"/>
            <GridViewColumn Header="内容列" DisplayMemberBinding="{Binding MyProperty3}"/>
        </GridView>
    </ListView.View>
</ListView>

ViewModel部分

CaseItemViewModel作为数据项

cs 复制代码
public class CaseItemViewModel
{
    public string MyProperty { get; set; }
    public string MyProperty1 { get; set; }
    public string MyProperty2 { get; set; }
    public string MyProperty3 { get; set; }
}

MainWindowViewModel作为上层ViewModel

cs 复制代码
public class MainWindowViewModel
{
    public List<CaseItemViewModel> MyPropertys { get; set; }

    public MainWindowViewModel()
    {
        MyPropertys = new List<CaseItemViewModel>
        {
            new CaseItemViewModel { MyProperty = "1", MyProperty1 = "1", MyProperty2 = "1", MyProperty3 = "1" },
            new CaseItemViewModel { MyProperty = "2", MyProperty1 = "2", MyProperty2 = "2", MyProperty3 = "2" },
            new CaseItemViewModel { MyProperty = "3", MyProperty1 = "3", MyProperty2 = "3", MyProperty3 = "3" },
            new CaseItemViewModel { MyProperty = "4", MyProperty1 = "4", MyProperty2 = "4", MyProperty3 = "4" },
            new CaseItemViewModel { MyProperty = "5", MyProperty1 = "5", MyProperty2 = "5", MyProperty3 = "5" }
        };
    }
}

设置MainWindowViewModel 到上层DataContext

cs 复制代码
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        // 设置上下文
        DataContext = new MainWindowViewModel();
    }
}

分析思路

ItemsControl 的子类控件,对应数据项多为xxxItem,该控件继承关系如下:

继承

[Object]-->[DispatcherObject]-->[DependencyObject]-->[Visual]-->[UIElement]-->[FrameworkElement]-->[Control]-->[ContentControl]-->[ListBoxItem]

派生

--->[ComboBoxItem]

--->[ListViewItem]

排查

通过Vs2022自带工具,查看对应的选中行页面对象。

选中行,开启三项。

鼠标悬浮,确认选择的是该元素节点。

点击转到实时可视化树,定位元素。弹出实时可视化树窗口。

可以看到已经选中节点,单击右键【显示属性】。

显示出对应的选中项实际UI元素当前属性。

其中属性关联项是ListBoxItem对应为IsSelected。是否可以考虑直接通过在数据模板中获取到UI 元素xxxItemIsSelected 较少ViewModel 中添加额外属性。

cs 复制代码
public class ListViewItem : ListBoxItem
{
	
}

public class ListBoxItem : ContentControl
{
	public bool IsSelected { get; set; }
}

解决办法

方式一

如果是使用的MvvM架构设计,可以为控件的子项ViewModel 添加 IsSelected属性,从数据的维度去控制数据模板内的具体操作,此处不展开细说,主要以方式二为主。

cs 复制代码
public class CaseItemViewModel
{
	// 省略重复项
    public bool IsSelected { get; set; }
}

方式二(推荐)

纯UI层级处理,通过Binding 机制中提供的FindAncestor 方式,直接获取上级 Item 控件项属性。好处是ViewModel中,不需要再为了页面交互添加额外属性。

xaml 复制代码
<ListView ItemsSource="{Binding MyPropertys}" IsManipulationEnabled="False">
    <ListView.View>
        <GridView>
            <!--该列获取ListViewItem中的IsSelected属性-->
            <GridViewColumn Header="操作列" >
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <!--使用Binding机制中的FindAncestor,查找到ListViewItem的IsSelected属性-->
                        <CheckBox Content="操作项" 
              IsChecked="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}" 
              Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}"></CheckBox>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
             <!--省略重复内容-->
        </GridView>
    </ListView.View>
</ListView>
运行效果

非选中效果。

选中行效果。

相关推荐
热心网友纯白1 小时前
开源项目Lethe Windows编译过程
windows
纸飞机√※3 小时前
windows下部署安装 ELK,nginx,tomcat日志分析
windows·nginx·elk·tomcat
yerennuo3 小时前
windows第七章 MFC类CWinApp介绍
c++·windows·mfc
AitTech3 小时前
C#性能优化技巧:利用Lazy<T>实现集合元素的延迟加载
开发语言·windows·c#
爱辉弟啦4 小时前
Windows FileZila Server共享电脑文件夹 映射21端口外网连接
linux·windows·mac·共享电脑文件夹
DanceDonkey6 小时前
自定义BeanPostProcessor实现自动注入标注了特定注解的Bean
windows
Joeysoda6 小时前
Java数据结构 (从0构建链表(LinkedList))
java·linux·开发语言·数据结构·windows·链表·1024程序员节
一个处女座的暖男程序猿6 小时前
MyBatis Plus 中常用的 Service 功能
linux·windows·mybatis
军训猫猫头9 小时前
56.命令绑定 C#例子 WPF例子
开发语言·c#·wpf
renhl2529 小时前
opengrok_使用技巧
windows