WPF 数据模板事件处理程序

本文关键字:事件处理 程序 数据 WPF | 更新日期: 2023-09-27 18:34:28

我扩展了ListView类,并在单独的资源文件中为它创建了两个DataTemplate。我的问题是如何在DataTemplate中为Checkbox(和其他项目(添加事件处理程序?

我的列表视图.cs

using System.Windows;
using System.Windows.Controls;
namespace WpfCustomControlLibrary1
{
    public class MyListView : ListView
    {
        public enum ListMode
        {
            List, ListCheck
        }
        public static readonly DependencyProperty ModeProperty = DependencyProperty.Register
        (
            "Mode",
            typeof(ListMode),
            typeof(MyListView),
            new PropertyMetadata(ListMode.List)
        );
        public ListMode Mode
        {
            get { return (ListMode)GetValue(ModeProperty); }
            set { SetValue(ModeProperty, value); }
        }
    }
}

MyListViewItem.cs

using System.Windows;
using System.Windows.Controls;
namespace WpfCustomControlLibrary1
{
    public class MyListViewItem:Control
    {
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register
        (
            "Text",
            typeof(string),
            typeof(MyListViewItem),
            new UIPropertyMetadata(string.Empty)
        );
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
        public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register
        (
            "IsChecked",
            typeof(bool),
            typeof(MyListViewItem),
            new UIPropertyMetadata(false)
        );
        public bool IsChecked
        {
            get { return (bool)GetValue(IsCheckedProperty); }
            set { SetValue(IsCheckedProperty, value); }
        }
    }
}

资源词典.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfCustomControlLibrary1">
    <DataTemplate x:Key="ItemTemplate_List">
        <TextBlock Text="{Binding Text}" HorizontalAlignment="Left"/>
    </DataTemplate>
    <DataTemplate x:Key="ItemTemplate_ListCheck">
        <Grid>
            <CheckBox IsChecked="{Binding IsChecked}"/>
            <TextBlock Text="{Binding Text}" Margin="20,0,0,0" HorizontalAlignment="Left"/>
        </Grid>
    </DataTemplate>
    <Style TargetType="{x:Type local:MyListView}">
        <Style.Triggers>
            <Trigger Property="Mode" Value="List">
                <Setter Property="ItemTemplate" Value="{StaticResource ItemTemplate_List}"/>
            </Trigger>
            <Trigger Property="Mode" Value="ListCheck">
                <Setter Property="ItemTemplate" Value="{StaticResource ItemTemplate_ListCheck}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</ResourceDictionary>

WPF 数据模板事件处理程序

您的问题涉及资源文件中Event handlers及其使用。 对代码隐藏的访问不能直接在资源文件中XAML存储中表示。

虽然您可以在用户控件的 XAML 中执行以下操作,

    <CheckBox Click="CheckBox_OnClick"/>

当样式在单独的资源目录中分离时,这根本不可能。

这就是 ICommand 接口非常有用的地方,通常在 ViewModel 上触发,但也可用于触发代码隐藏。 然后语法变为(如果您希望触发代码隐藏(:-

   <CheckBox Command="{Binding CheckBoxClickedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType='MyListView'}}"/>
这将

允许您在以下情况下触发MyListView类中的代码:

  1. 将名为 CheckBoxClickedCommand 的属性添加到 MyListView
  2. 在该
  3. 类的属性上添加用于ICommand的支持接口

通常使用 RelayCommand 实施,因此您可以提供 Lambda 表达式来简化实施。 在RelayCommand上快速搜索会给你一些指导。

这一切听起来都不错,直到您发现只有某些控件(例如 ButtonCheckboxRadioButton(将Command模式作为标准实现。

幸运的是,自 Blend 3 以来,我们现在有更多的空间使用行为ICommand模式,这也是您可能想要研究的东西。

  <CheckBox Command="{Binding CheckBoxClickedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="MouseEnter">
                <i:InvokeCommandAction Command="{Binding CheckBoxMouseEnterCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Checkbox>

在这里,其他事件(如 MouseEnter(可用于触发ICommand调用。 这也意味着不支持 Command= 属性的其他控件也可以调用代码隐藏。