WPF CommandParameter 在上下文菜单中设置时未更新
Posted
技术标签:
【中文标题】WPF CommandParameter 在上下文菜单中设置时未更新【英文标题】:WPF CommandParameter not updated when set in Context Menu 【发布时间】:2011-04-11 18:08:57 【问题描述】:我有一个带有多个文本框控件的 wpf 窗口。我需要应用一种通用样式,将上下文菜单应用于每个控件,并且我已将其全局定义如下,
<ContextMenu x:Key="textBoxMenu">
<Separator/>
<MenuItem Header="Affirm"
Command="Binding Path=AffirmCommand"
CommandParameter="Binding RelativeSource=RelativeSource AncestorType=x:Type TextBox,AncestorLevel=1"/>
</ContextMenu>
<Style TargetType="x:Type TextBox" x:Key="TextBoxAffirmMenuStyle">
<Setter Property="ContextMenu" Value="DynamicResource textBoxMenu" />
</Style>
我已经根据上下文菜单的目标(在本例中为文本框)使用命令来执行适当的方法。
为了唯一标识控件,我为每个控件的“Tag”属性设置了一个唯一的字符串,并从设置为目标文本框控件本身的命令参数访问此标记。
private bool CanAffirmExecute(object param)
string columnName = (param as FrameworkElement).Tag as string;
if (this.CheckIsAffirmed(columnName))
return true;
else
return false;
private void AffirmExecute(object param)
string columnName = (param as FrameworkElement).Tag as string;
this.Affirm(columnName);
这样做的问题是,一旦命令参数设置为特定控件, 当右键单击不同的控件时,它不会在随后的上下文菜单操作中改变。 Command 参数保持静态,仅获取第一个控件中设置的标记值。
我怎样才能让它工作,以便我可以使用命令访问控件的每个标记值?
谢谢。
【问题讨论】:
【参考方案1】:ContextMenu 位于其自己的可视化树的根部,因此任何使用 RelativeSource.FindAncestor 的绑定都不会越过 ContextMenu。
一种解决方法是使用具有 PlacementTarget 属性的两阶段绑定,如下所示, 并分析方法 OnAffirmCommand(object obj) 中的对象参数以控制您的行为。在这种情况下,对象是实际的 TextBox。
这里是上下文菜单定义:
<Window.Resources>
<ContextMenu x:Key="textBoxMenu">
<Separator/>
<MenuItem Header="Affirm"
Command="Binding Path=AffirmCommand"
CommandParameter="Binding PlacementTarget.Tag,
RelativeSource=RelativeSource FindAncestor,
AncestorType=x:Type ContextMenu"/>
</ContextMenu>
<Style TargetType="x:Type TextBox" x:Key="TextBoxAffirmMenuStyle">
<Setter Property="ContextMenu" Value="StaticResource textBoxMenu" />
</Style>
</Window.Resources>
这里是文本框:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" ContextMenu="StaticResource textBoxMenu" Tag="Binding RelativeSource=RelativeSource Self" Text="text in box 1"/>
<TextBox Grid.Row="1" ContextMenu="StaticResource textBoxMenu" Tag="Binding RelativeSource=RelativeSource Self" Text="text in box 2"/>
<TextBox Grid.Row="2" ContextMenu="StaticResource textBoxMenu" Tag="Binding RelativeSource=RelativeSource Self" Text="text in box 3"/>
</Grid>
这是来自 ViewModel 的命令代码:
public class MainViewModel : ViewModelBase
public ICommand AffirmCommand get; set;
public MainViewModel()
AffirmCommand = new DelegateCommand<object>(OnAffirmCommand, CanAffirmCommand);
private void OnAffirmCommand(object obj)
private bool CanAffirmCommand(object obj)
return true;
【讨论】:
谢谢赞博尼。我以稍微不同的方式实现了这一点。似乎命令参数只绑定一次。我所做的就是像您一样将 CommandTarget 绑定到放置目标,并将 CommandTarget 绑定到 CommandParameter。由于每次打开上下文菜单时都会更新 CommandTarget,因此命令参数返回目标控件。我认为您的建议与这种方法有些相似。 感谢您的评论,请在以后发布您的代码/解决方案作为其他人的答案。以上是关于WPF CommandParameter 在上下文菜单中设置时未更新的主要内容,如果未能解决你的问题,请参考以下文章
理解WPF Binding CommandParameter =“{Binding}”
使用 WPF + MVVM 中的 Command + CommandParameter 删除列表视图中的行