2009-08-15 6 views
6

Tengo una clase estática que contiene un RoutedUICommand que me gustaría usar en el enlace.Enlace a un RoutedUICommand que no está en el código subyacente

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; 
     } 
    } 
} 

Cuando intento crear un CommandBinding para este comando AddPage, VS hace un berrinche, quejándose de que no puede encontrar en AddPage_CanExecute Window1 ... que no tiene sentido teniendo en cuenta que todos los ejemplos que he visto indica este XAML debe estar bien teniendo en cuenta el código que tengo en su lugar:

<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> 

he intentado tampoco incluyendo la sección Menu.CommandBindings y el simple uso de este (según this question lo que sugiere esto, pero no es específico):

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

Eso detuvo el flujo de errores, pero el elemento del menú que genera siempre está deshabilitado. CanExecute nunca parece ser llamado. Supongo que la unión también está fallando en este caso, aunque más silenciosamente.

¿Por qué VS odia mi orden y se niega a buscar en el lugar correcto para encontrar los métodos Ejecutados y CanExecute? He visto una serie de ejemplos (en Pro WPF por Matthew McDonald y en varios tutoriales de comandos personalizados en línea) que han hecho esto como lo estoy haciendo.

Respuesta

11

A CommandBinding es como cualquier otro elemento en su árbol visual. Cualquier evento especificado en él será manejado por la raíz de su árbol visual (su Window en este caso). Eso significa que si mueve el AddPage_Executed y el AddPage_CanExecute al código de su ventana, funcionará. Esto le permite usar el mismo comando en muchos componentes de la interfaz de usuario, pero tiene diferentes controladores.

Veo, sin embargo, que su comando ejecuta cierta lógica contra su modelo de vista. Para ahorrarle tiempo y frustración, comprenda que los comandos enrutados son la solución incorrecta aquí. En su lugar, encapsular su comando en la vista de modelo de algo como esto:

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()); 
    } 
} 

Un DelegateCommand es una implementación de ICommand delegados que invoca para ejecutar el comando y Query. Eso significa que la lógica de comando está incluida en el comando y no necesita un CommandBinding para proporcionar manejadores (no necesita un CommandBinding). Por lo que su vista solo se une a la máquina virtual de la siguiente manera:

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

le sugiero que lea a través de esta serie de mensajes para darle más contexto:

+0

Gran respuesta. Me consiguió justo lo que necesitaba. He leído algunos tutoriales de MVVM y visto este tipo de uso de Comando antes, pero no podía recordar cómo hacerlo, así que recurrí a las soluciones que encontré en mis libros y búsquedas. Gracias por tu ayuda. – evizaer

+0

Precioso. Me estaba golpeando la cabeza en este ... aprender wpf + mvvm no es tan sencillo como me gustaría. RoutedUICommandos demasiado complejos para lo que pretendía y sabía que debería haber una manera más simple. @Kent, gracias por sus ejemplos y blog. –

Cuestiones relacionadas