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>
运行效果

非选中效果。

选中行效果。

相关推荐
暖馒9 小时前
Modbus应用层协议的深度剖析
网络·网络协议·c#·wpf·智能硬件
玉梅小洋10 小时前
Windows 10 Android 构建配置指南
android·windows
R1nG86311 小时前
HCCL vs NCCL代码级对比 hccl/algorithms/ vs nccl/src/collectives/ Ring算法实现差异
wpf·cann
风指引着方向15 小时前
归约操作优化:ops-math 的 Sum/Mean/Max 实现
人工智能·wpf
雨中风华16 小时前
Linux, macOS系统实现远程目录访问(等同于windows平台xFsRedir软件的目录重定向)
linux·windows·macos
听麟18 小时前
HarmonyOS 6.0+ 跨端智慧政务服务平台开发实战:多端协同办理与电子证照管理落地
笔记·华为·wpf·音视频·harmonyos·政务
yuuki23323318 小时前
【C++】继承
开发语言·c++·windows
非凡ghost19 小时前
PowerDirector安卓版(威力导演安卓版)
android·windows·学习·软件需求
疯狂敲代码的老刘20 小时前
JDK 1.6到25 全版本网盘合集 (Windows + Mac + Linux)
java·linux·windows·macos·jdk
love530love1 天前
Windows 下 GCC 编译器安装与排错实录
人工智能·windows·python·gcc·msys2·gtk·msys2 mingw 64