绑定到不在codebehind中的RoutedUICommand [英] Binding to a RoutedUICommand that's not in the codebehind

查看:145
本文介绍了绑定到不在codebehind中的RoutedUICommand的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个静态类,其中包含一个RoutedUICommand,我想在绑定中使用。

I have a static class which contains a RoutedUICommand that I would like to use in binding.

public static class CommandLibrary
{
    public static ProjectViewModel Project { get; set; }

    public static RoutedUICommand AddPage { get; private set; }

    static CommandLibrary()
    {
        AddPage = new RoutedUICommand("AddPage", "AddPage", typeof(CommandLibrary));

    }

    public static void AddPage_Executed(object sender, ExecutedRoutedEventArgs args)
    {
        Project.AddPage();
    }

    public static void AddPage_CanExecute(object sender, CanExecuteRoutedEventArgs args)
    {
        // We need a project before we can add pages.
        if (Project != null)
        {
            args.CanExecute = true;
        }
        else
        {
            // Did not find project, turning Add Page off.
            args.CanExecute = false;
        }
    }
}

CommandBinding为这个AddPage命令,VS引发一个发脾气,抱怨,它不能在Window1中找到AddPage_CanExecute ...这没有任何意义,考虑到我看到的所有示例表明这个XAML应该是罚款考虑到我已经到位的代码:

When I attempt to create a CommandBinding for this AddPage command, VS throws a tantrum, complaining that it can't find AddPage_CanExecute in Window1... Which makes no sense considering that all the examples I've seen indicate this XAML should be fine considering the code I have in place:

<Window x:Class="MyProject.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MyProject">
    <Menu>
        <Menu.CommandBindings>
            <CommandBinding Command="local:CommandLibrary.AddPage" 
                            Executed="AddPage_Executed" CanExecute="AddPage_CanExecute" />
        </Menu.CommandBindings>
        <MenuItem Header="_Page">
            <MenuItem Header="_New" Command="local:CommandLibrary.AddPage" />
        </MenuItem>
    </Menu>
</Window>

我也试过不包括Menu.CommandBindings部分, href =http://stackoverflow.com/questions/889234/cant-bind-command-from-menu-item-to-a-command-binding>此问题,这表明这是但不是具体的) :

I've also tried not including the Menu.CommandBindings section and simply using this (as per this question which suggests this but is not specific):

<MenuItem Header="_New" Command="{x:Static local:CommandLibrary.AddPage}" />

启动错误流程,但它生成的菜单项始终禁用! CanExecute从来没有似乎被调用。我假设绑定在这种情况下失败了,虽然更安静。

That staunched the flow of errors but the menu item it generates is always disabled! CanExecute never seems to get called. I'm assuming the binding is failing in this case, as well, though more quietly.

为什么VS讨厌我的命令,拒绝向右看地方找到Executed和CanExecute方法?我已经看到了一些例子(在 Pro WPF 由Matthew McDonald和几个在线的自定义命令教程),我做

Why does VS hate my command and refuse to look in the right place to find the Executed and CanExecute methods? I've seen a number of examples (in Pro WPF by Matthew McDonald and on several custom command tutorials online) that have done this as I am doing it.

推荐答案

CommandBinding 就像任何其他元素你的视觉树。在其上指定的任何事件将由视觉树的根(在这种情况下您的 Window )处理。这意味着如果你移动 AddPage_Executed AddPage_CanExecute 到你的Window代码后面,它会工作。这允许你在许多UI组件中使用相同的命令,但有不同的处理程序。

A CommandBinding is just like any other element in your visual tree. Any events specified on it will be handled by the root of your visual tree (your Window in this case). That means if you move the AddPage_Executed and AddPage_CanExecute to your Window's code behind, it will work. This allows you to use the same command in many UI components but have different handlers.

但是,我看到,你的命令对你的视图模型执行一些逻辑。为了节省你一些时间和沮丧,了解路由命令是这里错误的解决方案。相反,在你的视图模型中封装你的命令,像这样:

I see, however, that your command executes some logic against your view model. To save you some time and frustration, understand that routed commands are the wrong solution here. Instead, encapsulate your command in your view model something like this:

public class ProjectViewModel
{
    private readonly ICollection<PageViewModel> _pages;
    private readonly ICommand _addPageCommand;

    public ProjectViewModel()
    {
        _pages = new ObservableCollection<PageViewModel>();
        _addPageCommand = new DelegateCommand(AddPage);
    }

    public ICommand AddPageCommand
    {
        get { return _addPageCommand; }
    }

    private void AddPage(object state)
    {
        _pages.Add(new PageViewModel());
    }
}

A DelegateCommand ICommand ,它调用委托来执行和查询命令。这意味着命令逻辑都包含在命令中,您不需要 CommandBinding 来提供处理程序(您不需要 CommandBinding at all)。所以你的视图只是绑定到你的VM如下:

A DelegateCommand is an implementation of ICommand that invokes delegates to execute and query the command. That means the command logic is all wrapped up in the command and you don't need a CommandBinding to provide handlers (you don't need a CommandBinding at all). So your view just binds to your VM as follows:

<MenuItem Header="_New" Command="{Binding AddPageCommand}"/>

我建议你阅读这一系列的帖子,给你更多的上下文:

I suggest you read through this series of posts to give you more context:

  • View Models: POCOs versus DependencyObjects
  • ViewModel
  • DelegateCommand
  • ActiveAwareCommand

这篇关于绑定到不在codebehind中的RoutedUICommand的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆