我有一个带有几个文本框控件的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>
我已经使用Command来执行适当的方法,具体取决于上下文菜单的目标,在本例中是文本框。
为了唯一地识别控件,我使用唯一字符串设置每个控件的“Tag”属性,并从命令参数访问此标记,该参数设置为目标文本框Control本身。
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参数保持静态,只获取第一个控件中设置的标记值。
如何让这个工作,以便我可以使用命令访问控件的每个标记值?
感谢。
答案 0 :(得分:0)
ContextMenu位于其自己的可视树的根部,因此使用RelativeSource.FindAncestor的任何绑定都不会超过ContextMenu。
解决方法是使用与PlacementTarget属性的两阶段绑定,如下所示, 并分析方法OnAffirmCommand(object obj)中的object参数来控制你的行为。在这种情况下,对象是实际的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;
}
}