You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF ListView中Checkbox单选实现及点击控件获取问题

WPF ListView Checkbox 单选实现方案

问题分析

你之前尝试的两种方式都存在问题:

  • PreviewMouseLeftButtonDown 事件的 OriginalSource 不一定是 Checkbox(可能是其内部子元素),无法直接定位到点击的目标项;
  • GridViewColumn 没有 Click 事件,只有 GridViewColumnHeader 支持点击事件,且这不是你需要的点击Checkbox的场景。

正确实现步骤

1. 修改XAML,给Checkbox绑定Checked事件

在DataTemplate里的Checkbox直接添加Checked事件绑定,这样能直接捕获到点击的Checkbox:

<ListView x:Name="listCertificate" HorizontalAlignment="Left"  Margin="15,15,0,0" VerticalAlignment="Top" Width="350">
    <ListView.View>
        <GridView AllowsColumnReorder="true" ColumnHeaderToolTip="InfoPaquet">
            <GridViewColumn Header="Checked">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <!-- 添加Checked事件绑定 -->
                        <CheckBox IsChecked="{Binding Checked}" Checked="CheckBox_Checked"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn DisplayMemberBinding="{Binding NotBefore}">
                <GridViewColumnHeader>Valid From</GridViewColumnHeader>
            </GridViewColumn>
            <GridViewColumn DisplayMemberBinding="{Binding NotAfter}">
                <GridViewColumnHeader>Valid To</GridViewColumnHeader>
            </GridViewColumn>
            <GridViewColumn DisplayMemberBinding="{Binding Subject}">
                <GridViewColumnHeader>Subject</GridViewColumnHeader>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

2. PowerShell中编写事件处理逻辑

在窗口加载时初始化数据,并给CheckBox_Checked事件添加处理函数,实现单选逻辑:

基础版本(使用PSCustomObject)

# 窗口加载时初始化示例数据
$hash.Window.Add_Loaded({
    $certificates = @(
        [PSCustomObject]@{ 
            Checked = $false 
            NotBefore = [DateTime]"2023-01-01" 
            NotAfter = [DateTime]"2024-01-01" 
            Subject = "Certificate 1" 
        },
        [PSCustomObject]@{ 
            Checked = $false 
            NotBefore = [DateTime]"2023-02-01" 
            NotAfter = [DateTime]"2024-02-01" 
            Subject = "Certificate 2" 
        },
        [PSCustomObject]@{ 
            Checked = $false 
            NotBefore = [DateTime]"2023-03-01" 
            NotAfter = [DateTime]"2024-03-01" 
            Subject = "Certificate 3" 
        }
    )
    $hash.listCertificate.ItemsSource = $certificates
})

# 处理Checkbox选中事件
$hash.Window.Add_CheckBox_Checked({
    param($sender, $e)
    # 获取点击的Checkbox及其绑定的数据项
    $clickedCheckbox = $sender
    $currentItem = $clickedCheckbox.DataContext

    # 遍历所有项,取消其他项的选中状态
    foreach ($item in $hash.listCertificate.Items) {
        if ($item -ne $currentItem) {
            $item.Checked = $false
        }
    }
    # 确保当前项处于选中状态
    $currentItem.Checked = $true
    # 刷新ListView更新UI(因为PSCustomObject没有属性变更通知)
    $hash.listCertificate.Items.Refresh()
})

优化版本(实现INotifyPropertyChanged,自动更新UI)

如果希望UI自动更新,无需手动调用Items.Refresh(),可以创建一个实现INotifyPropertyChanged的类:

# 添加自定义数据类,实现属性变更通知
Add-Type -TypeDefinition @"
using System;
using System.ComponentModel;

public class CertificateItem : INotifyPropertyChanged {
    private bool _checked;
    public bool Checked {
        get { return _checked; }
        set {
            if (_checked != value) {
                _checked = value;
                OnPropertyChanged(nameof(Checked));
            }
        }
    }

    public DateTime NotBefore { get; set; }
    public DateTime NotAfter { get; set; }
    public string Subject { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName) {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
"@

# 窗口加载时初始化数据
$hash.Window.Add_Loaded({
    $certificates = @(
        [CertificateItem]@{ 
            Checked = $false 
            NotBefore = [DateTime]"2023-01-01" 
            NotAfter = [DateTime]"2024-01-01" 
            Subject = "Certificate 1" 
        },
        [CertificateItem]@{ 
            Checked = $false 
            NotBefore = [DateTime]"2023-02-01" 
            NotAfter = [DateTime]"2024-02-01" 
            Subject = "Certificate 2" 
        }
    )
    $hash.listCertificate.ItemsSource = $certificates
})

# 处理Checkbox选中事件
$hash.Window.Add_CheckBox_Checked({
    param($sender, $e)
    $currentItem = $sender.DataContext
    foreach ($item in $hash.listCertificate.Items) {
        if ($item -ne $currentItem) {
            $item.Checked = $false
        }
    }
    $currentItem.Checked = $true
})

3. 关于Add_Click等事件方法的说明

WPF控件的事件绑定需要对应控件实际支持的事件:

  • 只有继承自ButtonBase的控件(如Button、CheckBox)或特定控件(如GridViewColumnHeader)才有Click事件;
  • 对于自定义事件绑定,需要在XAML中声明事件名称(如上面的Checked="CheckBox_Checked"),然后在PowerShell中通过$Window.Add_事件名()的方式添加处理函数。

内容的提问来源于stack exchange,提问作者Stephan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:17:50