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

非选中效果。

选中行效果。

相关推荐
code_shenbing10 小时前
WPF实现打印机控制及打印
wpf
菜鸟单飞10 小时前
介绍一款非常实用的PDF阅读软件!
windows·pdf·电脑
流星白龙15 小时前
【Linux】35.封装 UdpSocket(2)
linux·运维·windows
waicsdn_haha15 小时前
Visual Studio Code 2025 安装与高效配置教程
c语言·ide·windows·vscode·微软·编辑器·win7
ChoSeitaku17 小时前
12.重复内容去重|添加日志|部署服务到Linux上(C++)
linux·c++·windows
Major_xx17 小时前
装win10系统提示“windows无法安装到这个磁盘,选中的磁盘采用GPT分区形式”解决方法
windows·gpt
CoderIsArt17 小时前
Windows图形开发库Kernel32,OpenGL32,Glu32,Gdi32与User32
windows
伪装成塔的小兵17 小时前
Windows使用docker部署fastgpt出现的一些问题
windows·docker·容器·oneapi·fastgpt
开开心心就好18 小时前
娱乐使用,可以生成转账、图片、聊天等对话内容
windows·python·智能手机·软件工程·娱乐·软件需求
~kiss~20 小时前
python的thrift2pyi学习
windows·python·学习