WPF - 为什么 ContextMenu 项目适用于 ListBox 而不是 ItemsControl?

2024-04-07

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

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

这是关于什么的ListBox允许带有命令的上下文菜单项正确绑定?

以下是我为突出问题而整理的示例应用程序的一些摘录:

<!-- 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}" />

以下是视图模型和数据项的 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提供允许其上下文菜单项命令正确绑定,有什么方法可以让它工作ItemsControl?


好的,我看到的主要问题是 ItemsControl 没有所选项目的概念,因此您无法选择要绑定到的 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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF - 为什么 ContextMenu 项目适用于 ListBox 而不是 ItemsControl? 的相关文章

  • 调试内存不足异常

    在修复我制作的小型 ASP NET C Web 应用程序的错误时 我遇到了 OutOfMemoryException 没有关于在哪里查看的提示 因为这是一个编译时错误 如何诊断此异常 我假设这正是内存分析发挥作用的地方 有小费吗 Thank
  • 转到 C# WPF 中的第一页

    我正在 WPF 中使用导航服务 为了导航到页面 我使用 this NavigationService Navigate new MyPage 为了返回我使用 this NavigationService GoBack 但是如何在不使用的情况
  • 过期时自动重新填充缓存

    我当前缓存方法调用的结果 缓存代码遵循标准模式 如果存在 则使用缓存中的项目 否则计算结果 在返回之前将其缓存以供将来调用 我想保护客户端代码免受缓存未命中的影响 例如 当项目过期时 我正在考虑生成一个线程来等待缓存对象的生命周期 然后运行
  • 对于 HTTPS,Request.UrlReferrer 为 NULL

    我在用 Request UrlReferrer AbsoluteUri 在我的项目中获取托管我的应用程序的 URL 如果我从 http 主机重定向 我可以获得 URL 但如果我从 https 主机重定向 我将得到 null 我怎样才能得到
  • 添加 LINQ 的 LongCount 扩展方法是否有实际原因?

    LINQ 有 2 种计算可枚举数的方法 Count and LongCount 实际上 这两者之间的唯一区别是第一个返回一个int 而第二个返回一个long 我不清楚为什么添加第二种方法 它的唯一用例似乎是处理超过 2B 元素的枚举 对我来
  • 使用Azure Service Fabric的默认客户端时如何向请求添加消息头?

    我想知道是否可以将自定义消息头注入到传出请求中以携带附加信息 而无需反序列化有效负载来完成身份验证 验证或请求关联等功能 例如通过消息检查器提供的 wcf Update 使用 SDK v2 您现在可以 相对 轻松地修改 Reliable S
  • 如何检查 FTP 目录是否存在

    寻找通过 FTP 检查给定目录的最佳方法 目前我有以下代码 private bool FtpDirectoryExists string directory string username string password try var r
  • 为什么 C# 4.0 中的可选参数需要编译时常量?

    还有一种方法可以使用可选方法参数的运行时值吗 可选参数必须是常量 因为它们是作为属性值写出的 因此 它们继承了属性值所具有的所有限制 无法直接对运行时值进行编码 但是您可以接近以下模式 public void MyApi SomeType
  • 限制对记录的访问。基于声明的权限是个好主意吗

    在 net 基于声明的身份框架中 如果我想限制用户对某个帐户 特定帐户 123456 执行操作 查看或编辑 我说的是商业实体 例如银行帐户 创建索赔是个好主意吗对于他们可以查看或编辑的每个帐户 一组中有很多索赔有什么缺点吗 系统管理员可能有
  • 应用服务中的内存利用率是否可​​以提高

    我有一个相当简单的 Web 应用程序在 Azure 的 B1 服务计划中的应用服务计划中运行 该计划提供 1 个 CPU 和 1 75GB RAM CPU 使用率永远不会超过 5 左右 内存使用率永远不会低于 52 我确实停止了计划中唯一运
  • 如何使用 ObjectDataProvider 将枚举绑定到 XAML 中的 ComboBox

    我正在尝试绑定一个Enum to a ComboBox 我见过很多人使用ObjectDataProvider但我似乎无法访问它 我还注意到有些人在一段时间内使用它Window Resources 而不是Page Resources但我找不到
  • 为什么即使当我尝试从工作线程更改 UI 时,同步上下文仍为空?为什么即使我不这样做,工作线程也会在 UI 线程上等待?

    我在表单上有一个按钮 点击它我调用FooAsync并在完成时阻止 UI 线程 下面是代码和我的问题 using System using System Diagnostics using System Threading using Sys
  • MonoState、Singleton 或派生形式:CRUD 应用程序的最佳方法?

    我有一个相当大的 CRUD WinForm 应用程序 其中有许多对象 人员 注册 计划 案例注释等 该应用程序由 30 多种表单组成 UI 逻辑上被分解 会员 注册 计划 案例说明等 我正在尝试弄清楚如何创建我的人物对象搜索后搜索表格并将对
  • 模拟对象 - 将所有方法声明为虚拟方法还是使用接口?

    与 Java 不同 net 中的方法默认不是虚拟的 为了使用大多数模拟对象框架 您要么必须将要在模拟上使用的方法标记为 真实 对象上的虚拟方法 要么必须有一个可以模拟被测试类将使用的接口接受代替执行 将每个方法标记为虚拟似乎是一种不好的形式
  • 将复选框添加到 UniformGrid

    我正在尝试将复选框动态添加到 wpf 中的统一网格中 但看起来网格没有为它们分配足够的空间 所以它们都有点互相重叠 这就是我将它们添加到后面的代码中的方法 foreach string folder in subfolders PathCh
  • 实时服务器上的 woff 字体 MIME 类型错误

    我有一个 asp net MVC 4 网站 我在其中使用 woff 字体 在 VS IIS 上运行时一切正常 然而 当我将 pate 上传到 1and1 托管 实时服务器 时 我得到以下信息 网络错误 404 未找到 http www co
  • 将 xml 反序列化为类,list<> 出现问题

    我有以下 XML
  • 插入记录后如何从SQL Server获取Identity值

    我在数据库中添加一条记录identity价值 我想在插入后获取身份值 我不想通过存储过程来做到这一点 这是我的代码 SQLString INSERT INTO myTable SQLString Cal1 Cal2 Cal3 Cal4 SQ
  • 从固定文档中删除页面?

    如何从固定文档中删除页面 我添加这样的页面 Add page to pageContent PageContent pageContent new PageContent IAddChild pageContent AddChild fix
  • 将文本叠加在图像背景上并转换为 PDF

    使用 NET 我想以编程方式创建一个 PDF 它仅包含一个背景图像 其上有两个具有不同字体和位置的标签 我已阅读过有关现有 PDF 库的信息 但不知道 如果适用 哪一个对于如此简单的任务来说最简单 有人愿意指导我吗 P D 我不想使用生成的

随机推荐

  • 如何解决 C# 中机器人的干扰问题?

    我做了一个电报机器人 事实上 机器人是一个游戏 玩猜某些单词 但问题是当我将机器人添加到两个不同的组 作为管理员 或两个用户 Telegram 分别使用机器人和启动机器人时 会产生影响一个人的游戏对下一个人的游戏造成干扰 例如 如果 joh
  • Visual Studio 15.8.1 不运行 MS 单元测试

    当我将 Visual Studio 更新到最新版本时 我的一个测试项目停止运行测试并输出以下消息 测试项目 未引用任何 NET NuGet 适配器 测试 发现或执行可能不适用于该项目 这是 建议在每个测试项目中引用 NuGet 测试适配器
  • 向下浮动和双倍值的向下函数

    如何将下限函数应用于浮点或双精度值以获取整数 我得到双精度值 4 4497083717E10 float 值 4 4497084E10 从我的函数中出来 我得到的下限值为 Double 下限 4 4497083717E10 float 下限
  • GPUImage :将过滤器应用于现有视频文件

    我试图使用视频过滤器GPUImage框架 我跟着过滤和重新编码电影 http www sunsetlakesoftware com 2012 02 12 introducing gpuimage framework教程 它给了我错误Unkn
  • 如何在 SpiderMonkey JavaScript 中获取控制台输入?

    我目前正在使用 Spidermonkey 来运行我的 JavaScript 代码 我想知道是否有一个函数可以从控制台获取输入 类似于 Python 的做法 var raw input 或者在 C 中 std cin gt gt var 我环
  • 如何在 PostgreSQL 中的换行符上将一个值拆分为多行?

    我有一个名为BookInfo具有以下结构 id book name description 1 book 1 harry potter Part 2 2 我怎样才能分割该行 id 1 在换行符上分成多行 以便harry n potter n
  • iOS 14 - 如何以编程方式打开默认邮件应用程序?

    使用 iOS14 用户可以将不同的电子邮件客户端应用程序设置为默认值 有没有办法以编程方式打开选定的默认邮件应用程序 Using mailto URL 将默认邮件应用程序设置为 Gmail 后 不执行任何操作 显然你必须添加mailto t
  • 禁用 eclipselink 缓存和查询缓存 - 不起作用?

    我正在使用 eclipselink JPA 和数据库 该数据库也在我的应用程序外部进行更新 因此 我想每隔几秒钟查询一些表 即使我尝试禁用缓存和查询缓存 我也无法使其工作 例如 EntityManagerFactory entityMana
  • Google Maps Api 直线(最短)路线

    我目前正在尝试找到一种使用 Google Maps Api V3 获得直线路线的方法 我已经设法使用地理编码和方向服务来获取从 A 点到 B 点的路线 包括两条替代路线 我还尝试过 禁止高速公路 和 禁止通行费 但似乎没有什么可以完全解决这
  • 无法使用命令行解释器

    我尝试在 php 解释器中执行简单的 php 代码 当我执行命令时php a我收到消息 启用交互模式 没有任何地方可以输入 php 但我可以通过命令执行php代码php r 例如 php r echo Hello stackoverflow
  • zclip 在 jquery ui 非活动选项卡中不起作用

    我在用zclip http www steamdev com zclip 在我的 asp net 网页上的 jQuery UI 选项卡中的 jQuery UI 对话框中 它在第一个处于活动状态的选项卡中效果很好 但当我将其添加到第二个选项卡
  • 如何从 Git 存储库中删除文件?

    我怎样才能删除 file1 txt 从我的存储库 Use git rm https git scm com docs git rm 如果您想从 Git 存储库中删除该文件和文件系统 use git rm file1 txt git comm
  • SQL 将一列的值分组到另一列

    SQL 中是否有某种 聚合 函数可以将值转换为列表 一个示例可能是以下形式的表格 game id player score 1 fred 2 1 tom 1 2 fred 3 2 tom 4 我想要返回的是一个如下所示的表 player s
  • 在 postgres 中分割人名的最简单方法?

    考虑一个包含人类全名的表 create table names full name varchar not null insert into names full name values Jane Marie Doe John Doe 在
  • 在Python中分割句子

    我正在尝试将句子分成单词 words content lower split 这给了我这样的单词列表 evening and there was morning the first day 并使用以下代码 def clean up list
  • 使用表单方法将隐藏输入值设置为要提交的 blob

    我正在尝试提交一个表单 其中一个 blob 附加到一个隐藏的输入标签 如下所示
  • 增加溢出宽度以调整滚动条

    当滚动条可见时 我应该使用什么 CSS 来使 div 调整其宽度 这是场景 我有一个 div 和子元素 div ul li li li li li li ul ul li li li li li li ul div 我想在溢出时自动调整滚动
  • 带注释的代码风格[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我无法在两者之间做出决定 MyAnnotation param1 paramval public void foo and MyAnnotati
  • 将 CSS 属性排序为任意顺序?

    我想以编程方式将样式表中的所有声明 属性 不是声明块本身 而是每个块内的各个声明 排序为任意顺序 我已经能够在网上找到几种按字母顺序排序声明的方法 或者按字母顺序反向排序 甚至按字符串长度排序 但这对我来说没有帮助 因为这些排序方法本质上是
  • WPF - 为什么 ContextMenu 项目适用于 ListBox 而不是 ItemsControl?

    列表中的项目有上下文菜单 上下文菜单项绑定到路由命令 如果列表控件是一个 则上下文菜单项可以正常工作ListBox 但一旦我将其降级为ItemsControl它不再起作用了 具体来说 菜单项始终呈灰色 这CanExecute回调在我的Com