我已在窗口的顶部使用菜单创建 RichTextBox 控件。 MenuItems 调用命令 - 它完美无缺。然后我尝试在 RichTextBox 中创建ContextMenu,并希望像 MenuItems 中那样调用相同的命令。 因此,我以与 MenuItems 相同的方式绑定ContextMenu,但它会抛出 NullReferenceException 。
可能是什么原因。我应该如何将命令绑定到ContextMenu?
以下是我的代码部分
MenuItem代码:
<MenuItem Name="FontSettings" Header="Font settings" Command="{Binding FontSettingsCommand}" CommandParameter="{Binding ElementName=MainRichTbx}" />
RichTextBox代码:
<RichTextBox Name="MainRichTbx" TextBlock.LineHeight="0.1" Margin="5" >
<RichTextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Font settings" Command="{Binding FontSettingsCommand}" CommandParameter="{Binding ElementName=MainRichTbx}" />
</ContextMenu>
</RichTextBox.ContextMenu>
</RichTextBox>
我要执行的那个命令:
private ICommand _FontSettingsCommand; public ICommand FontSettingsCommand { get { if (_FontSettingsCommand == null) { _FontSettingsCommand = new RelayCommand( argument => EditorFormat.SetFont(argument), argument => true ); } return _FontSettingsCommand; } }
我在Command中调用的方法:
public static void SetFont(object control)
{
FontDialog fontDialog = new FontDialog();
if (fontDialog.ShowDialog() == DialogResult.OK)
{
(control as System.Windows.Controls.RichTextBox).FontFamily = new System.Windows.Media.FontFamily(fontDialog.Font.Name);
(control as System.Windows.Controls.RichTextBox).FontSize = fontDialog.Font.Size;
(control as System.Windows.Controls.RichTextBox).FontStyle = fontDialog.Font.Italic ? FontStyles.Italic : FontStyles.Normal;
(control as System.Windows.Controls.RichTextBox).FontWeight = fontDialog.Font.Bold ? FontWeights.Bold : FontWeights.Regular;
}
}
和RelayCommand类
class RelayCommand : ICommand
{
private readonly Action<object> _Execute;
private readonly Func<object, bool> _CanExecute;
public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
{
if (execute == null) throw new ArgumentNullException("execute");
_Execute = execute;
_CanExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _CanExecute == null ? true : _CanExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add
{
if (_CanExecute != null) CommandManager.RequerySuggested += value;
}
remove
{
if (_CanExecute != null) CommandManager.RequerySuggested -= value;
}
}
public void Execute(object parameter)
{
_Execute(parameter);
}
}
答案 0 :(得分:1)
我有一个我认为有效的解决方案,绑定到上下文菜单的PlacementTarget。
<RichTextBox Name="MainRichTbx" TextBlock.LineHeight="0.1" Margin="5" >
<RichTextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Font settings"
Command="{Binding FontSettingsCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=PlacementTarget}" />
</ContextMenu>
</RichTextBox.ContextMenu>
</RichTextBox>
但是,XAML设计器强调CommandPamameter并显示工具提示“RelativeSource不在FindAncestor模式下”。然而它似乎有效。
修改强>
添加模式= FindAncestor似乎修复了错误消息。我不知道它对这种行为是否有任何影响。
<RichTextBox Name="MainRichTbx" TextBlock.LineHeight="0.1" Margin="5" >
<RichTextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Font settings"
Command="{Binding FontSettingsCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget}" />
</ContextMenu>
</RichTextBox.ContextMenu>
</RichTextBox>
答案 1 :(得分:0)
这可能是因为绑定无法找到您的文本框。
这是因为( echo foo | /usr/bin/cat ) &
不是可视树的一部分,因此找不到ContextMenu
的文本框。
解决此问题的最佳方法是根本不使用CommandParameter
,而是在ViewModel中使用变量(例如CommandParameter
)。
但是,您可以通过命名SelectedTextBox
并在View的构造函数中设置其NameScope来获得一个有效(但稍微丑陋)的解决方案:
ContextMenu
这应该可以正常工作。