WPF:列表框项目上下文菜单/菜单项上的命令即使在按钮上也不起作用
WPF: Command on listbox item context menu / menu item does not work even though it does on a button
我有一个自定义的 RoutedUICommand,它在绑定到按钮的命令 属性 时工作正常。然而,当绑定到列表框项目上的 ConextMenu MenuItem 时,它不起作用。未调用 CanExecute 方法,因此该项目在上下文菜单中处于禁用状态。但是,从按钮的绑定调用 CanExecute。
在下面的回购示例中,CrawlCommands.AddCredit
是命令。它绑定到按钮和 ListBoxItems。 Button 的行为符合预期,但 ListBoxItem 的行为却并非如此。右键单击列表框项目确实会显示上下文菜单,并且菜单项的 header 正确地从命令中派生,但从未调用 CanExecute,因此它永远不知道命令有效并因此保持禁用状态。
我错过了什么?
<UserControl x:Class="CrawlSpace.TestCommands"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CrawlSpace"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Background="#FF020523">
<UserControl.CommandBindings>
<CommandBinding Command="local:CrawlCommands.AddCredit" Executed="ExecutedAddCredit" CanExecute="CanExecuteAddCredit"/>
</UserControl.CommandBindings>
<Grid>
<Grid.Resources>
<local:MockData x:Key="TestData"/>
</Grid.Resources>
<Grid.Background>
<SolidColorBrush Color="DarkGray"/>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="7*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<!-- A button with a command, this one works! -->
<Button x:Name="button" Command="local:CrawlCommands.AddCredit" Content="Add Credit" Margin="10" Grid.Row="1" Width="177"/>
<ListBox x:Name="listBox" Margin="10" Background="LightBlue" ItemsSource="{StaticResource TestData}">
<ListBox.Resources>
<!-- Define a context menu -->
<ContextMenu x:Key="ItemMenu">
<MenuItem Command="local:CrawlCommands.AddCreditBlock"/>
</ContextMenu>
<!-- Sets a context menu for each ListBoxItem in the current ListBox -->
<Style TargetType="{x:Type ListBoxItem}">
<!-- This menu item will not function even though the button verison above does -->
<Setter Property="ContextMenu" Value="{StaticResource ItemMenu}"></Setter>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
参考我的代码。它对我来说很好用。
<UserControl x:Class="DragDrop_Learning.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:local="clr-namespace:DragDrop_Learning"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.CommandBindings>
<CommandBinding Command="local:CrawlCommands.AddCredit" Executed="ExecutedAddCredit" CanExecute="CanExecuteAddCredit"/>
<CommandBinding Command="local:CrawlCommands.AddCreditBlock" Executed="ExecutedAddCreditBlock" CanExecute="CanExecuteAddCreditBlock"/>
</UserControl.CommandBindings>
<Grid>
<Grid.Resources>
</Grid.Resources>
<Grid.Background>
<SolidColorBrush Color="DarkGray"/>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="7*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<!-- A button with a command, this one works! -->
<Button x:Name="button" Command="local:CrawlCommands.AddCredit" Content="Add Credit" Margin="10" Grid.Row="1" Width="177"/>
<ListBox x:Name="listBox" Margin="10" Background="LightBlue" >
<ListBox.Resources>
<!-- Define a context menu -->
<ContextMenu x:Key="ItemMenu">
<MenuItem Command="local:CrawlCommands.AddCreditBlock"/>
</ContextMenu>
<!-- Sets a context menu for each ListBoxItem in the current ListBox -->
<Style TargetType="{x:Type ListBoxItem}">
<!-- This menu item will not function even though the button verison above does -->
<Setter Property="ContextMenu" Value="{StaticResource ItemMenu}"></Setter>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
List<Person> lst = new List<Person>();
listBox.ItemsSource = lst;
lst.Add(new Person() { FirstName="Test"});
}
private void CanExecuteAddCredit(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void ExecutedAddCredit(object sender, ExecutedRoutedEventArgs e)
{
}
private void CanExecuteAddCreditBlock(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void ExecutedAddCreditBlock(object sender, ExecutedRoutedEventArgs e)
{
}
}
public static class CrawlCommands
{
public static readonly RoutedUICommand AddCredit = new RoutedUICommand
(
"AddCredit",
"AddCredit",
typeof(CrawlCommands)
);
public static readonly RoutedUICommand AddCreditBlock = new RoutedUICommand
(
"AddCreditBlock",
"AddCreditBlock",
typeof(CrawlCommands)
);
}
class Person
{
private string myVar;
public string FirstName
{
get { return myVar; }
set { myVar = value; }
}
}
我有一个自定义的 RoutedUICommand,它在绑定到按钮的命令 属性 时工作正常。然而,当绑定到列表框项目上的 ConextMenu MenuItem 时,它不起作用。未调用 CanExecute 方法,因此该项目在上下文菜单中处于禁用状态。但是,从按钮的绑定调用 CanExecute。
在下面的回购示例中,CrawlCommands.AddCredit
是命令。它绑定到按钮和 ListBoxItems。 Button 的行为符合预期,但 ListBoxItem 的行为却并非如此。右键单击列表框项目确实会显示上下文菜单,并且菜单项的 header 正确地从命令中派生,但从未调用 CanExecute,因此它永远不知道命令有效并因此保持禁用状态。
我错过了什么?
<UserControl x:Class="CrawlSpace.TestCommands"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CrawlSpace"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Background="#FF020523">
<UserControl.CommandBindings>
<CommandBinding Command="local:CrawlCommands.AddCredit" Executed="ExecutedAddCredit" CanExecute="CanExecuteAddCredit"/>
</UserControl.CommandBindings>
<Grid>
<Grid.Resources>
<local:MockData x:Key="TestData"/>
</Grid.Resources>
<Grid.Background>
<SolidColorBrush Color="DarkGray"/>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="7*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<!-- A button with a command, this one works! -->
<Button x:Name="button" Command="local:CrawlCommands.AddCredit" Content="Add Credit" Margin="10" Grid.Row="1" Width="177"/>
<ListBox x:Name="listBox" Margin="10" Background="LightBlue" ItemsSource="{StaticResource TestData}">
<ListBox.Resources>
<!-- Define a context menu -->
<ContextMenu x:Key="ItemMenu">
<MenuItem Command="local:CrawlCommands.AddCreditBlock"/>
</ContextMenu>
<!-- Sets a context menu for each ListBoxItem in the current ListBox -->
<Style TargetType="{x:Type ListBoxItem}">
<!-- This menu item will not function even though the button verison above does -->
<Setter Property="ContextMenu" Value="{StaticResource ItemMenu}"></Setter>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
参考我的代码。它对我来说很好用。
<UserControl x:Class="DragDrop_Learning.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:local="clr-namespace:DragDrop_Learning"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.CommandBindings>
<CommandBinding Command="local:CrawlCommands.AddCredit" Executed="ExecutedAddCredit" CanExecute="CanExecuteAddCredit"/>
<CommandBinding Command="local:CrawlCommands.AddCreditBlock" Executed="ExecutedAddCreditBlock" CanExecute="CanExecuteAddCreditBlock"/>
</UserControl.CommandBindings>
<Grid>
<Grid.Resources>
</Grid.Resources>
<Grid.Background>
<SolidColorBrush Color="DarkGray"/>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="7*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<!-- A button with a command, this one works! -->
<Button x:Name="button" Command="local:CrawlCommands.AddCredit" Content="Add Credit" Margin="10" Grid.Row="1" Width="177"/>
<ListBox x:Name="listBox" Margin="10" Background="LightBlue" >
<ListBox.Resources>
<!-- Define a context menu -->
<ContextMenu x:Key="ItemMenu">
<MenuItem Command="local:CrawlCommands.AddCreditBlock"/>
</ContextMenu>
<!-- Sets a context menu for each ListBoxItem in the current ListBox -->
<Style TargetType="{x:Type ListBoxItem}">
<!-- This menu item will not function even though the button verison above does -->
<Setter Property="ContextMenu" Value="{StaticResource ItemMenu}"></Setter>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
List<Person> lst = new List<Person>();
listBox.ItemsSource = lst;
lst.Add(new Person() { FirstName="Test"});
}
private void CanExecuteAddCredit(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void ExecutedAddCredit(object sender, ExecutedRoutedEventArgs e)
{
}
private void CanExecuteAddCreditBlock(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void ExecutedAddCreditBlock(object sender, ExecutedRoutedEventArgs e)
{
}
}
public static class CrawlCommands
{
public static readonly RoutedUICommand AddCredit = new RoutedUICommand
(
"AddCredit",
"AddCredit",
typeof(CrawlCommands)
);
public static readonly RoutedUICommand AddCreditBlock = new RoutedUICommand
(
"AddCreditBlock",
"AddCreditBlock",
typeof(CrawlCommands)
);
}
class Person
{
private string myVar;
public string FirstName
{
get { return myVar; }
set { myVar = value; }
}
}