绑定到RoutedUICommand,这不是在代码隐藏 [英] Binding to a RoutedUICommand that's not in the codebehind

查看:135
本文介绍了绑定到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抛出发脾气,抱怨它不能在窗口1找到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>这表明这一点,但这个问题是不特定)

<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恨我的命令,拒绝在正确的看地方找到的执行,CanExecute方法吗我已经看到了很多例子(中的临WPF 的马修·麦克唐纳和几个自定义命令教程在线)已经做到了这一点,因为我做这件事。

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.

推荐答案

A 的CommandBinding 就像其他任何元素你的视觉树。它指定的任何事件都会被你的视觉树(你的窗口在这种情况下)的根进行处理。这意味着如果你移动 AddPage_Executed AddPage_CanExecute 你的窗口的后面的代码,它会工作。这使您可以在许多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());
    }
}

一个的 DelegateCommand 的ICommand的实现调用委托执行和查询命令。这意味着在命令命令逻辑都包裹起来,你并不需要一个的CommandBinding 来提供处理程序(你并不需要一个的CommandBinding 在所有)。所以,你的看法刚刚绑定到你的虚拟机,如下所示:

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

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

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