WPF 如何将命令绑定到 RichTextBox 中的 ContextMenu?
WPF How to bind a command to the ContextMenu in RichTextBox?
我在 Window[= 的顶部用 Menu 创建了 RichTextBox 控件40=]。 MenuItems 调用命令 - 它工作得很好。然后我尝试在 RichTextBox 中创建 ContextMenu,并希望调用与 MenuItems 中相同的命令。
因此,我以与 MenuItems 相同的方式绑定 ContextMenu,但它抛出 NullReferenceException.
可能是什么原因。我应该如何将命令绑定到上下文菜单?
下面是我的部分代码
菜单项代码:
<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;
}
}
我在命令中调用的方法:
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
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);
}
}
这可能是因为绑定找不到您的文本框。
发生这种情况是因为 ContextMenu
不是可视化树的一部分,因此找不到 CommandParameter
的文本框。
解决此问题的最佳方法是根本不使用 CommandParameter
,而是在 ViewModel 中使用一个变量(例如 SelectedTextBox
)。
但是,您可以通过命名 ContextMenu
并在视图的构造函数中设置其 NameScope 来获得有效(但稍微丑陋)的解决方案:
NameScope.SetNameScope(myContextMenu, this);
这应该可以正常工作。
我有一个我认为有效的解决方案,绑定到上下文菜单的 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 is not in FindAncestor mode"。尽管如此它似乎工作。
编辑
添加 Mode=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>
我在 Window[= 的顶部用 Menu 创建了 RichTextBox 控件40=]。 MenuItems 调用命令 - 它工作得很好。然后我尝试在 RichTextBox 中创建 ContextMenu,并希望调用与 MenuItems 中相同的命令。 因此,我以与 MenuItems 相同的方式绑定 ContextMenu,但它抛出 NullReferenceException.
可能是什么原因。我应该如何将命令绑定到上下文菜单?
下面是我的部分代码
菜单项代码:
<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; } }
我在命令中调用的方法:
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
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);
}
}
这可能是因为绑定找不到您的文本框。
发生这种情况是因为 ContextMenu
不是可视化树的一部分,因此找不到 CommandParameter
的文本框。
解决此问题的最佳方法是根本不使用 CommandParameter
,而是在 ViewModel 中使用一个变量(例如 SelectedTextBox
)。
但是,您可以通过命名 ContextMenu
并在视图的构造函数中设置其 NameScope 来获得有效(但稍微丑陋)的解决方案:
NameScope.SetNameScope(myContextMenu, this);
这应该可以正常工作。
我有一个我认为有效的解决方案,绑定到上下文菜单的 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 is not in FindAncestor mode"。尽管如此它似乎工作。
编辑
添加 Mode=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>