我是 MVVM 模式的新手,我遇到了列表视图内复选框的问题。 当我将复选框作为项目放入列表视图时,事件“已选中”和“未选中”不会触发。 但是当我在列表视图之外添加一个复选框时,例如在堆栈面板中,事件触发。
有人能解释一下这个问题吗?
提前谢谢您。
这是我使用的代码:
xmlns:behav="http://schemas.microsoft.com/xaml/behaviors"
<Border Grid.Row="1" Grid.Column="0" BorderThickness="2" Grid.RowSpan="3" BorderBrush="{StaticResource MainMenuColor}">
<ListBox ItemsSource="{Binding ListBoxItems}" Background="Transparent" Foreground="{StaticResource MainMenuColor}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox FontFamily="{StaticResource FontProtokoll}" IsChecked="{Binding IsChecked}" Content="{Binding Path=Text}" Foreground="{StaticResource MainMenuColor}">
<behav:Interaction.Triggers>
<behav:EventTrigger EventName="Checked">
<behav:InvokeCommandAction Command="{Binding CheckedOrUncheckedCommand}"/>
</behav:EventTrigger>
</behav:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
CheckBox
继承了 DataContext
绑定的 ListBox.ItemsSource
,即 ListBoxItems
。您可能正在尝试调用主 Command
中的 ViewModel
。假设,为了正确绑定到 ViewModel
,您需要执行类似的操作。
xmlns:behav="http://schemas.microsoft.com/xaml/behaviors"
<Border Grid.Row="1" Grid.Column="0" BorderThickness="2" Grid.RowSpan="3" BorderBrush="{StaticResource MainMenuColor}">
<ListBox ItemsSource="{Binding ListBoxItems}" Background="Transparent" Foreground="{StaticResource MainMenuColor}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox FontFamily="{StaticResource FontProtokoll}" IsChecked="{Binding IsChecked}" Content="{Binding Path=Text}" Foreground="{StaticResource MainMenuColor}">
<behav:Interaction.Triggers>
<behav:EventTrigger EventName="Checked">
<behav:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=DataContext.CheckedOrUncheckedCommand}"/>
</behav:EventTrigger>
</behav:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
CheckBox
现在直接绑定到它的父级 ListBox
s DataContext
以及其中的 CheckedOrUncheckedCommand
。
此外,您还可以根据您的用例使用
IsChecked
属性绑定作为替代方案。
尚不清楚您的
DataContext
实际上是什么样子(即 CheckedOrUncheckedCommand
的定义位置)。因为您编写的命令在 DataTemplate
之外的元素上设置绑定时会正确调用,所以看起来您绑定到了错误的 DataContext
。DataContext
的 DataTemplate
是 always 模板化数据项本身。就您而言,它是 ItemsSource
内的项目。Binding.RelativeSource
属性来修复绑定,也可以在元素树中查找公开正确 DataContext
的元素。在你的情况下,该元素应该是父元素 ListBox
:
<DataTempate>
<!-- DataContext is the templated data item.
In this case its the item inside the `ListBoxItems` source collection that is bound to the ItemsSource. -->
<CheckBox>
<behav:Interaction.Triggers>
<behav:EventTrigger EventName="Checked">
<behav:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=DataContext.CheckedOrUncheckedCommand}"/>
</behav:EventTrigger>
</behav:Interaction.Triggers>
</CheckBox>
</DataTemplate>
但是,
CheckedOrUncheckedCommand
的交互触发器绝对是多余的,应该删除。CheckBox
是 ButtonBase
,因此也是 ICommandSource
。只需将命令绑定到 CheckBox.Command
属性即可:
<CheckBox Command="{Binding CheckedOrUncheckedCommand}" />
并且由于您已经将
CheckBox.IsChecked
属性绑定到同一数据源,因此您可以完全删除该命令(或 IsChecked
绑定)。
仅使用其中之一,CheckBox.IsChecked
或 CheckBox.Command
。
使用
CheckBox.Command
:
<CheckBox Command="{Binding CheckedOrUncheckedCommand}" />
private bool IsEnabled { get; set; }
private void ExecuteCheckedOrUncheckedCommand(object commandParameter)
{
// Optionally set a property using the XOR operator to toggle it
// (CheckBox is a ToggleButton)
this.IsEnabled ^= true;
}
或者使用
CheckBox.IsChecked
属性:
<CheckBox IsChecked="{Binding IsEnabled}" />
// TODO::Property must raise the INotifyPropertyChanged.PropertyChanged event
private bool isEnabled;
public bool IsEnabled
{
get => this.isEnabled;
set
{
this.isEnabled = value;
OnPropertyChanged(nameof(this.IsEnabled));
OnIsEnabledChanged();
}
private void OnIsEnabledChanged()
{
ExecuteCheckedOrUncheckedCommand(null);
}
private void ExecuteCheckedOrUncheckedCommand(object commandParameter)
{
}
我在WinUI3中遇到了类似的问题,没错,我们需要定义控件的DataContext。就我而言,我在 DataGrid 的分组标题中定义了一个复选框。我需要的是,当单击组标题中的复选框时,可以选择该组中的所有复选框项目。
<Interactions:EventTriggerBehavior EventName="Checked"
SourceObject="{Binding ElementName=_groupCheckBox}">
<Interactions:InvokeCommandAction Command="{Binding ElementName=_dataGrid, Path=DataContext.GroupCheckedCommand}"
CommandParameter="{x:Bind PropertyValue}" />
</Interactions:EventTriggerBehavior>