【问题标题】:How do I add a custom routed command in WPF?如何在 WPF 中添加自定义路由命令?
【发布时间】:2010-10-10 17:25:12
【问题描述】:

我有一个包含菜单和子菜单的应用程序。我已将应用命令附加到一些子菜单项,例如剪切、复制和粘贴。
我还有一些其他菜单项没有应用程序命令。
如何将自定义命令绑定添加到这些子菜单项?
我浏览了this 文章,但无法将事件附加到我的子菜单项。

【问题讨论】:

标签: c# wpf


【解决方案1】:

我使用放置在 Window1 类(或任何窗口类的名称)之后的静态类,在其中创建 RoutedUICommand 类的实例:

public static class Command {

    public static readonly RoutedUICommand DoSomething = new RoutedUICommand("Do something", "DoSomething", typeof(Window1));
    public static readonly RoutedUICommand SomeOtherAction = new RoutedUICommand("Some other action", "SomeOtherAction", typeof(Window1));
    public static readonly RoutedUICommand MoreDeeds = new RoutedUICommand("More deeds", "MoreDeeeds", typeof(Window1));

}

在窗口标记中添加一个命名空间,使用 Window1 类所在的命名空间:

xmlns:w="clr-namespace:NameSpaceOfTheApplication"

现在我可以为命令创建绑定,就像为应用程序命令创建绑定一样:

<Window.CommandBindings>
    <CommandBinding Command="ApplicationCommands.Open" Executed="CommandBinding_Open" />
    <CommandBinding Command="ApplicationCommands.Paste" Executed="CommandBinding_Paste" />
    <CommandBinding Command="w:Command.DoSomething" Executed="CommandBinding_DoSomething" />
    <CommandBinding Command="w:Command.SomeOtherAction" Executed="CommandBinding_SomeOtherAction" />
    <CommandBinding Command="w:Command.MoreDeeds" Executed="CommandBinding_MoreDeeds" />
</Window.CommandBindings>

并在菜单中使用绑定,例如:

<MenuItem Name="Menu_DoSomething" Header="Do Something" Command="w:Command.DoSomething" />

【讨论】:

  • 拥有 static 类来保存 RoutedUICommands 是我的关键。 (如果它们在我的 Window1 类中,XAML 找不到它们。)谢谢!
  • 静态类的重要性真的不能低估。令人沮丧的是,如果命令是在非静态类中定义的,WPF 似乎会默默地忽略命令。
  • 为什么投反对票?如果你不解释你认为错的地方是什么,它就无法改进答案。
  • 仅供参考 - 不要犯我犯的同样的菜鸟错误:静态属性(例如 Command.DoSomething)必须是 public,否则您将收到以下异常 “CommandConverter 无法从 System.String 转换”。我假设这是因为管理命令的代码可能位于不同的程序集中,因此看不到 internal 属性。我上周刚开始学习 WPF :D
  • 我在 Google 上搜索了很多,直到我找到了这个简洁明了的说明如何做事。谢谢!
【解决方案2】:

与其在静态类中定义它们,不如直接在 XAML 中声明命令。示例(改编自 Guffas 的好示例):

<Window.Resources>
    <RoutedUICommand x:Key="DoSomethingCommand" Text="Do Something" />
    <RoutedUICommand x:Key="DoSomethingElseCommand" Text="Do Something Else" />
</Window.Resources>
<Window.CommandBindings>
    <CommandBinding Command="{StaticResource DoSomethingCommand}" Executed="CommandBinding_DoSomething" />
    <CommandBinding Command="{StaticResource DoSomethingElseCommand}" Executed="CommandBinding_DoSomethingElse" />
</Window.CommandBindings>
...
<MenuItem Name="Menu_DoSomething" Header="Do Something" Command="{StaticResource DoSomethingCommand}" />

【讨论】:

  • 这些是否绑定到实际的 C# 代码?如果是这样,怎么做? RoutedUICommands 有什么用途?他们添加了什么功能?
  • @EdJ.Plunkett:1. 是的。 2.通过CommandBindings:CommandBinding_DoSomethingCommandBinding_DoSomethingElse是C#代码。 3./4.有关 RoutedCommands 与常规 Button_Click 绑定的优势的一般性讨论,请参阅joshsmithonwpf.wordpress.com/2008/03/18/…(“谁在乎?”部分)。
  • 谢谢。我想知道 RoutedUICommands 相对于 Guffa 的示例添加了什么,而不是相对于常规到老式的 onclick 处理(如果我理解你 - 如果我必须这样做,我不会问所有这些!),但我会在 Josh Smith 的文章中查找。
  • @EdJ.Plunkett:啊,好的。 Guffa 还使用 RoutedUICommands,他只是在静态类中而不是在 XAML 中声明它们。这是他的例子和我的例子之间的唯一区别。这是您希望在哪里拥有它们的偏好问题。
  • 我最喜欢这个答案。干净多了。
【解决方案3】:

我知道我的回答为时已晚,但我希望它对未来有所帮助。

我喜欢 Guffa 和 Heinzi 的答案,但您只能使用一个命令来实现上一个结果。 我通常使用Help命令

 <Window.CommandBindings>
        <CommandBinding Command="{StaticResource Help}" Executed="HelpExecuted" />
  </Window.CommandBindings>

我在每次调用时都使用 CommandParametr,例如

<Window.InputBindings>
    <KeyBinding Command="{StaticResource Help}" Key="A" Modifiers="Ctrl" CommandParameter="Case1"/>
    <KeyBinding Command="{StaticResource Help}" Key="B" Modifiers="Ctrl" CommandParameter="Case2"/>
    <KeyBinding Command="{StaticResource Help}" Key="C" Modifiers="Ctrl" CommandParameter="Case3"/>
    <KeyBinding Command="{StaticResource Help}" Key="D" Modifiers="Ctrl" CommandParameter="Case4"/>
    <MouseBinding Command="{StaticResource Help}" MouseAction="LeftDoubleClick" CommandParameter="Case5" />
</Window.InputBindings>

<Button Command="Help" CommandParameter="Case6" Content="Button">
    <Button.InputBindings>
        <KeyBinding Command="{StaticResource Help}" Gesture="Ctrl+D" CommandParameter="Case7"/>
    </Button.InputBindings>
</Button>

在cs文件中

private void HelpExecuted(object sender, ExecutedRoutedEventArgs e)
{
    string str = e.Parameter as string;
    switch (str)
    {
        case null://F1 Pressed default Help
               //Code
            break;
        case "Case1":
               //Code
            break;
        case "Case2":
               //Code
            break;
        case "Case3":
               //Code
            break;
        case "Case4":
            break;
        case "Case5":
               //Code
            break;
        case "Case6":
               //Code
            break;
        case "Case7":
               //Code
            break;
    }
    e.Handled = true;
}

如果你使用的是 MVVM 模式

private void HelpExecuted(object sender, ExecutedRoutedEventArgs e)
{
    string str = e.Parameter as string;
    Mvvm_Variable.Action(Input: str);
    e.Handled = true;
}

并将开关移至 ViewModule 站点。和 Action 是同一个 ViewModule 类中的一个方法。

【讨论】:

  • 就是票!使用 Command 的 Properties 值为我开辟了许多新的可能性 :-) 我刚刚使用 ApplicationCommands.NotACommand 和 MinimizeWindow、MaximizeWindow 和 RestoreDownWindow 的属性
  • 我喜欢这个(任何减少样板的东西!),但值得注意的是它确实有一个限制 - 例如,菜单条目中包含的文本是按命令定义的,所以如果您需要(或以后可能添加)菜单,这种方法可能不是最好的(我也经常将按钮标签绑定到命令文本)。
  • @Bob,这是一个简单的 switch 语句,限制是您将使用所有反映命令参数字符串的快捷方式组合。在这种情况下,即使路由命令也无济于事。
  • 对不起@Waleed,我没有关注你。不过,也许我并不清楚。 Guffa 和 Heinzi 在他们的答案中都使用RoutedUICommand。此类具有Text 属性,从中获取文本以自动填充调用该命令的菜单条目(并且可以在其他地方使用 - 我经常通过共享模板将按钮文本绑定到它)。如果您使用一个命令(例如,“帮助”),所有菜单项都将具有在Help.Text 中定义的同一段文本。根据您喜欢的架构,这可能不是什么大问题,但我认为这是需要注意的事情。
  • 对不起@Bob 我想念你,谢谢你的解释
猜你喜欢
  • 2018-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-18
相关资源
最近更新 更多