WPF:将 ListBox ContextMenu 的命令参数绑定到 ListBox 的选定项
Posted
技术标签:
【中文标题】WPF:将 ListBox ContextMenu 的命令参数绑定到 ListBox 的选定项【英文标题】:WPF: Binding the command parameter for ListBox ContextMenu to the Selected Item of the ListBox 【发布时间】:2017-07-22 17:24:46 【问题描述】:是否可以将 ListBox ContextMenu 的 CommandParameter 绑定到 ListBox 的选定项?我应该说 ContCommand 在主窗口中,并在单击上下文菜单项时调用它 - 但是,我需要让参数正常工作。
我试过了,但绑定失败:
<Window x:Class="ListBoxContextMenu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ListBoxContextMenu"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<TextBlock Text="ListBox here:"/>
<ListBox ItemsSource="Binding Items" MinHeight="100" TabIndex="0" x:Name="LB">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Foo" Command="Binding ContCommand" CommandParameter="Binding RelativeSource=RelativeSource AncestorType=x:Type ListBox,Path=SelectedItem"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
</StackPanel>
</Grid>
</Window>
MainWindow 的 C# 代码:
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using MvvmFoundation.Wpf;
namespace ListBoxContextMenu
public partial class MainWindow : Window
public MainWindow()
InitializeComponent();
DataContext = this;
Loaded += (sender, e) => MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
ContCommand = new RelayCommand<object>((object o) =>
System.Diagnostics.Debug.WriteLine("Context Menu pressed");
);
public ObservableCollection<string> Items get; set; = new ObservableCollection<string>"Fred", "Jim", "Sheila";
public RelayCommand<object> ContCommand get; set;
【问题讨论】:
删除代码示例中不相关的项。比如using
/NameSpace
和Window属性。只关注阅读它的人的组成部分。
【参考方案1】:
上下文菜单位于不同的树上,因此根据具体情况进行绑定很棘手。这里有两个选项:
1 通过名称绑定到列表框,例如
Binding SelectedItem, ElementName=LB
2使用参考名称
有时元素名称绑定失败,必须使用 x:ref 名称(您拥有)
Binding Source=x:Reference LB, Path=SelectedItem
至于为什么,引用x:Reference
在 WPF 和 XAML 2006 中,元素引用由 ElementName 绑定的框架级功能处理。对于大多数 WPF 应用程序和方案,仍应使用 ElementName 绑定。此一般指南的例外情况可能包括存在数据上下文或其他范围考虑因素导致数据绑定不切实际以及不涉及标记编译的情况。
【讨论】:
<MenuItem Header="Foo" Command="Binding ContCommand" CommandParameter="Binding SelectedItem, ElementName=LB"/>
产生绑定错误:System.Windows.Data 错误:4:找不到引用“ElementName=LB”的绑定源。绑定表达式:路径=选定项;数据项=空;目标元素是'MenuItem'(名称='');目标属性是'CommandParameter'(类型'Object')
@AdrianS 你试过 x:reference 绑定了吗?
x:reference 绑定导致抛出异常: System.Windows.Markup.XamlParseException: 'Cannot call MarkupExtension.ProvideValue 因为循环依赖。 MarkupExtension 内的属性不能引用引用 MarkupExtension 结果的对象。受影响的 MarkupExtensions 是:'System.Windows.Data.Binding' 行号 '18' 和行位置 '80'。'【参考方案2】:
将Mode=FindAncestor
添加到RelativeSource
绑定。
CommandParameter="Binding RelativeSource=RelativeSource Mode=FindAncestor, AncestorType=x:Type ListBox, Path=SelectedItem"
【讨论】:
我得到“System.Windows.Data 错误:4:找不到与引用'RelativeSource FindAncestor,AncestorType='System.Windows.Controls.ListBox',AncestorLevel='1'' 绑定的源。 BindingExpression:Path=SelectedItem;DataItem=null;目标元素是'MenuItem'(Name='');目标属性是'CommandParameter'(类型'Object')"【参考方案3】:ListBox
不是 ContextMenu
的视觉祖先,因为后者驻留在自己的视觉树中。
但您可以绑定到ContextMenu
的PlacementTarget
,即ListBox
。
这行得通:
<ListBox ItemsSource="Binding Items" MinHeight="100" TabIndex="0" x:Name="LB">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Foo" Command="Binding ContCommand"
CommandParameter="Binding RelativeSource=RelativeSource AncestorType=x:Type ContextMenu,
Path=PlacementTarget.SelectedItem"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
【讨论】:
【参考方案4】:而不是将其绑定到列表框,而是将其绑定到已单击的列表框项 他是有关的!不是他持有你正在寻找的对象的列表框
<ListBox x:Name="lstAllTags" FocusVisualStyle="x:Null" ItemsSource="Binding ResearchedTagsResult" Margin="0" Background="x:Null" BorderBrush="x:Null" ItemTemplate="DynamicResource SearchTagDataTemplate" FontFamily="Consolas" Foreground="DynamicResource x:Static SystemColors.InfoBrushKey" MouseMove="LstAllTags_MouseMove" MouseLeave="LstAllTags_MouseLeave" HorizontalContentAlignment="Stretch" Focusable="False" FontSize="13" SelectionChanged="LstTags_SelectionChanged" BorderThickness="0">
<ListBox.Resources>
<!--Defines a context menu-->
<ContextMenu x:Key="ContextMenu">
<MenuItem Command="Binding DeleteTagCmd " CommandParameter="Binding RelativeSource=RelativeSource Mode=FindAncestor, AncestorType=x:Type ListBoxItem, Path=DataContext" Foreground="DynamicResource AppTextForeground" DataContext="DynamicResource TagManagement_instance" Header="Edit" BorderBrush="#FF919191" BorderThickness="0" Padding="0">
<MenuItem.Icon>
<Image Source="/Resx/pencil.png"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListBox.Resources>
</ListBox>
【讨论】:
以上是关于WPF:将 ListBox ContextMenu 的命令参数绑定到 ListBox 的选定项的主要内容,如果未能解决你的问题,请参考以下文章