2009-02-17 16 views
5

Estaba hablando con alguien hoy sobre cómo elegir un patrón de diseño para manejar la lógica en su programa WPF y esperando que la comunidad SO pueda ayudar con más consejos para facilitar la decisión. ¿Qué factores a favor de los comandos superan las molestias?WPF utilizando RoutedUICommands personalizados o controladores de eventos simples?

me preparó un completo sample junto con algunos UML diagrams de los primeros dos de los tres enfoques:

  1. Uso Haga clic en los controladores de eventos de botones y menús.
  2. Utilice los comandos vinculados en XAML.
  3. Utilice los comandos vinculados en el código, con el XAML guardado para el diseño y la interfaz GUI puro.

El curso introductorio en el que había estado y muchos de los libros muestran simples controladores de eventos Click como la forma natural de conectar la lógica a los objetos de la interfaz de usuario.

Estaba un poco sorprendido por la cantidad de sobrecarga necesaria para usar los comandos tanto con el comando que se creó en el código detrás de archivo:

public static readonly ICommand cmdShow2 = new RoutedUICommand(
    "Show Window2", "cmdShow2", 
    typeof(TestDespatchWindow)); 

y luego aún más código en el XAML con la forma prolija la comando tiene que ser identificado y vinculado:

<Window x:Class="WPFDispatchDemo.TestDespatchWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:w="clr-namespace:WPFDispatchDemo"..> 

    <Window.CommandBindings> 
     <CommandBinding Command="{x:Static w:TestDespatchWindow.cmdShow2}" 
     Executed="OnShow2" /> 
    </Window.CommandBindings> 
     <DockPanel> 
     <StackPanel Margin="0,8,0,0"> 
      <Button x:Name="Show2EventBased" 
        Margin="10,2,10,2" 
        Click="OnShow2" 
        Content="Show2 via WPF Event"/> 
      <Button x:Name="Show2Command" 
        Command="{x:Static w:TestDespatchWindow.cmdShow2}" 
        Margin="10,2,10,2" 
        Content="Show2 via WPF"/> 
     </StackPanel> 
    </DockPanel> 
    </Window> 

puedo (todavía) no pretende ser un experto en WPF así que pude haber pintado las cosas como más complejo de lo que realmente son, pero mi sospecha es que no se puede simplificar las cosas mucho más que lo anterior.

Editar:

me encontré con una interesante 3-way comparison entre DelegateCommand, RoutedCommand y eventos.

+0

¿Esto es una pregunta? –

+0

"¿Qué factores a favor de los comandos superan a los inconvenientes?" me parece una pregunta. Pensé que la cantidad de fondo podría hacer que sea más fácil para la gente ver que soy serio y entender el contexto. –

Respuesta

6

Manda sus ventajas y desventajas, tiene que elegir en función de su situación, Le recomiendo que haga esa elección en cada caso, no elija "la única manera verdadera" para todo el proyecto.

En algunos casos, la separación entre emisor y receptor y la capacidad de enviar comandos utilizando solo XAML es una gran ventaja (para un buen ejemplo, mire cómo la plantilla de control ScrollBar se comunica con la lógica de control en http://msdn.microsoft.com/en-us/library/ms742173.aspx).

En otros casos, los comandos pueden convertir lo que hubiera sido un controlador de eventos de 2 líneas en una monstruosidad imposible de seguir que implica el cambio de 4 lugares separados en la aplicación (How should the ViewModel close the form?).

3

La única razón es tener un registro de comandos bien conocido. Significa que los eventos probablemente sean métodos privados y siento que están estrechamente vinculados al código de la ventana. Al mismo tiempo, Commands le da la capacidad de mantener la implementación (evento) y la definición (Command) por separado, incluso puede usar otra clase (eche un vistazo a ApplicationCommands).

Además, cuando estoy haciendo mi trabajo WPF utilizo la implementación de ICommand (Command Pattern). Toda la lógica del comando va al método Execute. Esto me ayuda a mantener la separación de la lógica de una manera más estructurada sin una complicación excesiva del código de la ventana. Con esta opción, puedes crear comandos en tu modelo y, por lo tanto, unirlos sin ruido. Echar un vistazo.

Crear modelo.

public class Model 
{ 
    ICommand CloseMessagePopupCommand {get; set;} 
} 

A continuación, asigne Contexto de datos

public MainWindow() 
{ 

    this.DataContext = new Model(); 
} 

Y el uso follwing código XAML.

<Button 
    Command="{Binding CloseMessagePopupCommand}" 
    Content="{StaticResource Misc.Ok}" /> 
2

Trato de permanecer fiel al patrón de comando que Mike se refiere a la hora de desarrollar aplicaciones WPF, utilizando una combinación de de Andy # 2 y # 3 enfoques.

Solo puedo pensar en una desventaja de los comandos en mi opinión: solo ciertas acciones de ciertos elementos de la IU invocan comandos. Una forma de evitar esto es hacer que su controlador de eventos llame al método Execute en un comando. Creo que los comandos proporcionan una muy buena manera de encapsular la lógica de ejecución. Si mantienes una gran pieza de UI e implementas usando un patrón MVC/MVC/MVVM, esto se vuelve muy evidente.

Te animo a que veas la serie de Dan Crevier en el patrón DataModel-View-ViewModel, en particular la sección sobre Comandos y Comandos Encapsulantes. Incluso si este patrón no satisface sus necesidades, ofrece una gran visión general de cómo puede encapsular la lógica dentro de una clase separada.

1

Otras variaciones en ICommand parecen ser una forma popular de implementar estructuras complejas de comandos.

Brian Noyes en su article on PRISM dice

comandos de enrutado en WPF son muy potentes y útiles, pero tienen algunas deficiencias cuando se aplica a una aplicación compuesta. La primera es que están completamente acoplados al árbol visual: el invocador tiene que ser parte del árbol visual, y el enlace del comando debe vincularse a través del árbol visual. ... El segundo inconveniente es que están estrechamente vinculados con el árbol de enfoque de la interfaz de usuario y continúa hablando de DelegateCommand y CompositeCommand que incluye CAL (Prism).

Cuestiones relacionadas