gpt4 book ai didi

.net - WPF - 为什么 ContextMenu 项目适用于 ListBox 但不适用于 ItemsControl?

转载 作者:行者123 更新时间:2023-12-03 21:41:36 24 4
gpt4 key购买 nike

列表中的项目有上下文菜单。上下文菜单项绑定(bind)到路由命令。

如果列表控件是 ListBox,则上下文菜单项可以正常工作,但一旦我将其降级为 ItemsControl,它就不再有效。具体来说,菜单项始终显示为灰色。我的 CommandBinding 中的 CanExecute 回调也没有被调用。

ListBox 允许带有命令的上下文菜单项正确绑定(bind)的原因是什么?

以下是我为了突出问题而放在一起的示例应用程序的一些摘录:

<!-- Data template for items -->
<DataTemplate DataType="{x:Type local:Widget}">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="UseWidget"
Command="{x:Static l:WidgetListControl.UseWidgetCommand}"
CommandParameter="{Binding}" />
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=Price}" />
</StackPanel>
</DataTemplate>

<!-- Binding -->
<UserControl.CommandBindings>
<CommandBinding Command="{x:Static l:WidgetListControl.UseWidgetCommand}"
Executed="OnUseWidgetExecuted"
CanExecute="CanUseWidgetExecute" />
</UserControl.CommandBindings>

<!-- ItemsControl doesn't work... -->
<ItemsControl ItemsSource="{Binding Path=Widgets}" />

<!-- But change it to ListBox, and it works! -->
<ListBox ItemsSource="{Binding Path=Widgets}" />

这是 View 模型和数据项的 C# 代码:

public sealed class WidgetListViewModel
{
public ObservableCollection<Widget> Widgets { get; private set; }

public WidgetViewModel()
{
Widgets = new ObservableCollection<Widget>
{
new Widget { Name = "Flopple", Price = 1.234 },
new Widget { Name = "Fudge", Price = 4.321 }
};
}
}

public sealed class Widget
{
public string Name { get; set; }
public double Price { get; set; }
}

这是控件的 C# 代码隐藏:

public partial class WidgetListControl
{
public static readonly ICommand UseWidgetCommand
= new RoutedCommand("UseWidget", typeof(WidgetListWindow));

public WidgetListControl()
{
InitializeComponent();
}

private void OnUseWidgetExecuted(object s, ExecutedRoutedEventArgs e)
{
var widget = (Widget)e.Parameter;
MessageBox.Show("Widget used: " + widget.Name);
}

private void CanUseWidgetExecute(object s, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.Handled = true;
}
}

只是重申这个问题——ListBox 提供的是什么允许它的上下文菜单项命令正确绑定(bind),有什么方法可以让 ItemsControl 工作?

最佳答案

好的,我看到的主要问题是 ItemsControl 没有所选项目的概念,因此您无法为要绑定(bind)的 DataTemplate 选择项目。

我不记得我是在哪里看到它的,但是在编写 WPF 时要遵循的一个好的规则是使用为您提供所需行为的控件,然后将其设置为您想要的样式。

考虑到这一点,您想要 ListBox 的行为,而不是 ItemsControl 的外观,那么为什么不设置 ListBoxItems 的样式以不显示选中和未选中之间的差异。

<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="2,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border SnapsToDevicePixels="true" x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

关于.net - WPF - 为什么 ContextMenu 项目适用于 ListBox 但不适用于 ItemsControl?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/833607/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com