tutorial implementar como beginner advantages wpf mvvm

wpf - implementar - Buenos ejemplos de plantilla MVVM



wpf c# mvvm (9)

Actualmente estoy trabajando con la plantilla Microsoft MVVM y encuentro frustrante la falta de ejemplos detallados. El ejemplo incluido de ContactBook muestra muy poco manejo de comandos y el único otro ejemplo que he encontrado proviene de un artículo de MSDN Magazine donde los conceptos son similares pero usan un enfoque ligeramente diferente y aún carecen de complejidad. ¿Hay algún ejemplo de MVVM decente que al menos muestre las operaciones CRUD básicas y el cambio de diálogo / contenido?

Las sugerencias de todos fueron realmente útiles y comenzaré a compilar una lista de buenos recursos

Marcos / Plantillas

Artículos útiles

Vídeos de pantalla

Bibliotecas adicionales


¿Has mirado a Caliburn ? La muestra de ContactManager tiene muchas cosas buenas. Las muestras genéricas de WPF también proporcionan una buena visión general de los comandos. La documentación es bastante buena y los foros están activos. ¡Recomendado!



El proyecto de muestra en el Cinch muestra las herramientas CRUD y de navegación básicas. Es un buen ejemplo del uso de MVVM e incluye un artículo de varias partes que explica su uso y motivaciones.



He escrito un ejemplo simple de MVVM desde cero en el proyecto de código. Aquí está el enlace MVVM WPF paso a paso . Comienza desde una simple arquitectura de 3 capas y te gradúa para utilizar un framework como PRISM.


Incluso yo compartí la frustración hasta que tomé el asunto en mis manos. Empecé IncEditor.

IncEditor ( http://inceditor.codeplex.com ) es un editor que intenta introducir desarrolladores a WPF, MVVM y MEF. Lo comencé y logré obtener algunas funcionalidades como el soporte ''tema''. No soy experto en WPF, MVVM o MEF, así que no puedo poner mucha funcionalidad en él. Les pido sinceramente a ustedes que lo mejoren para que los fanáticos como yo podamos entenderlo mejor.


Jason Dolinger hizo un buen screencast de MVVM. Como Egor mencionó, no hay un solo buen ejemplo. Ellos han terminado. La mayoría son buenos ejemplos de MVVM, pero no cuando se trata de problemas complejos. Todos tienen su propio camino. Laurent Bugnion también tiene una buena forma de comunicarse entre viewmodels. http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx Cinch es también un buen ejemplo. Paul Stovel tiene una buena post que también explica mucho con su framework Magellan.


Lamentablemente, no existe una gran aplicación de ejemplo de MVVM que haga de todo, y hay muchos enfoques diferentes para hacer las cosas. En primer lugar, es posible que desee familiarizarse con uno de los frameworks de aplicaciones (Prism es una opción decente), ya que le proporcionan herramientas convenientes como inyección de dependencia, comando, agregación de eventos, etc. para probar fácilmente diferentes patrones que se adaptan a usted .

El lanzamiento del prisma:
Prism

Incluye una aplicación de ejemplo bastante decente (el operador de bolsa) junto con muchos ejemplos más pequeños y cómo hacerlo. Por lo menos, es una buena demostración de varios subpatrones comunes que las personas usan para hacer que MVVM realmente funcione. Ellos tienen ejemplos tanto para CRUD como para diálogos, creo.

Prism no es necesariamente para cada proyecto, pero es algo bueno para familiarizarse.

CRUD: Esta parte es bastante fácil, las vinculaciones bidireccionales de WPF hacen que sea realmente fácil editar la mayoría de los datos. El verdadero truco es proporcionar un modelo que facilite la configuración de la IU. Como mínimo, debe asegurarse de que su ViewModel (u objeto comercial) implemente INotifyPropertyChanged para admitir el enlace y pueda vincular propiedades directamente a los controles de la UI, pero también puede implementar IDataErrorInfo para la validación. Normalmente, si usa algún tipo de solución ORM, configurar CRUD es muy fácil.

Este artículo demuestra operaciones simples crud: http://dotnetslackers.com/articles/wpf/WPFDataBindingWithLINQ.aspx

Se basa en LinqToSql, pero eso es irrelevante para el ejemplo: todo lo que es importante es que sus objetos comerciales implementen INotifyPropertyChanged (las clases generadas por LinqToSql sí). MVVM no es el objetivo de ese ejemplo, pero no creo que importe en este caso.

Este artículo demuestra la validación de datos
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx

De nuevo, la mayoría de las soluciones ORM generan clases que ya implementan IDataErrorInfo y generalmente proporcionan un mecanismo para facilitar el agregado de reglas de validación personalizadas.

La mayoría de las veces puede tomar un objeto (modelo) creado por algún ORM y envolverlo en un ViewModel que lo mantiene y comandos para guardar / eliminar, y está listo para enlazar la UI directamente a las propiedades del modelo.

La vista se vería así (ViewModel tiene un Item propiedad que contiene el modelo, como una clase creada en el ORM):

<StackPanel> <StackPanel DataContext=Item> <TextBox Text="{Binding FirstName, Mode=TwoWay, ValidatesOnDataErrors=True}" /> <TextBox Text="{Binding LastName, Mode=TwoWay, ValidatesOnDataErrors=True}" /> </StackPanel> <Button Command="{Binding SaveCommand}" /> <Button Command="{Binding CancelCommand}" /> </StackPanel>

Diálogos: Diálogos y MVVM son un poco difíciles. Prefiero usar un sabor del enfoque de Mediator con los diálogos, puede leer un poco más al respecto en esta pregunta de :
Dialogs

Mi enfoque habitual, que no es muy clásico MVVM, se puede resumir de la siguiente manera:

Una clase base para un diálogo ViewModel que expone los comandos para las acciones de confirmación y cancelación, un evento que le permite a la vista saber que un diálogo está listo para ser cerrado, y cualquier otra cosa que necesite en todos sus cuadros de diálogo.

Una vista genérica para su diálogo: puede ser una ventana o un control de tipo de superposición "modal" personalizado. En esencia, es un presentador de contenido en el que volcamos el modelo de vista y maneja el cableado para cerrar la ventana; por ejemplo, en el cambio de contexto de datos puede verificar si el nuevo ViewModel se hereda de su clase base, y si es así, suscribirse al evento de cierre relevante (el controlador asignará el resultado del diálogo). Si proporciona funcionalidad de cierre universal alternativo (el botón X, por ejemplo), debe asegurarse de ejecutar también el comando de cierre relevante en el modelo de vista.

En algún lugar donde necesite proporcionar plantillas de datos para sus ViewModels, pueden ser muy simples, especialmente dado que probablemente tenga una vista para cada diálogo encapsulado en un control separado. La plantilla de datos predeterminada para un ViewModel se vería así:

<DataTemplate DataType="{x:Type vmodels:AddressEditViewModel}> <views:AddressEditView DataContext={Binding} /> </DataTemplate>

La vista de diálogo debe tener acceso a estos, porque de lo contrario no sabrá cómo mostrar ViewModel, además de la interfaz de usuario compartida, sus contenidos son básicamente los siguientes:

<ContentControl Content={Binding} />

La plantilla de datos implícita asignará la vista al modelo, pero ¿quién la lanzará?

Esta es la parte no tan mvvm. Una forma de hacerlo es usar un evento global. Lo que creo que es mejor hacer es usar una configuración de tipo de agregador de eventos, proporcionada a través de la inyección de dependencia: de esta forma, el evento es global para un contenedor, no para toda la aplicación. Prism usa el marco de unidad para la semántica de contenedor y la inyección de dependencia, y en general me gusta bastante Unity.

Normalmente, tiene sentido que la ventana raíz se suscriba a este evento: puede abrir el cuadro de diálogo y establecer su contexto de datos en el modelo de vista que se transfiere con un evento elevado.

Configurar esto de esta manera permite a ViewModels pedirle a la aplicación que abra un diálogo y responda a las acciones del usuario allí sin saber nada sobre la UI, por lo que en su mayor parte, la MVVM-ness permanece completa.

Sin embargo, hay veces en que la interfaz de usuario tiene que levantar los diálogos, lo que puede hacer que las cosas sean un poco más complicadas. Considere por ejemplo, si la posición del diálogo depende de la ubicación del botón que la abre. En este caso, debe tener alguna información específica de UI cuando solicite un diálogo abierto. Generalmente creo una clase separada que contiene un ViewModel y alguna información de UI relevante. Desafortunadamente, algunos acoplamientos parecen inevitables allí.

Seudocódigo de un manejador de botones que genera un diálogo que necesita datos de posición del elemento:

ButtonClickHandler(sender, args){ var vm = DataContext as ISomeDialogProvider; // check for null var ui_vm = new ViewModelContainer(); // assign margin, width, or anything else that your custom dialog might require ... ui_vm.ViewModel = vm.SomeDialogViewModel; // or .GetSomeDialogViewModel() // raise the dialog show event }

La vista de diálogo se vinculará a los datos de posición y pasará el ViewModel contenido al ContentControl interno. El ViewModel en sí mismo todavía no sabe nada sobre la UI.

En general, no hago uso de la propiedad de retorno DialogResult del método ShowDialog() o espero que el hilo se bloquee hasta que se cierre el diálogo. Un diálogo modal no estándar no siempre funciona así, y en un entorno compuesto, a menudo no se desea que un controlador de eventos bloquee de esa manera. Prefiero dejar que ViewModels se ocupe de esto: el creador de un ViewModel puede suscribirse a sus eventos relevantes, establecer métodos de confirmación / cancelación, etc., por lo que no hay necesidad de confiar en este mecanismo de UI.

Entonces, en lugar de este flujo:

// in code behind var result = somedialog.ShowDialog(); if (result == ...

Yo suelo:

// in view model var vm = new SomeDialogViewModel(); // child view model vm.CommitAction = delegate { this.DoSomething(vm); } // what happens on commit vm.CancelAction = delegate { this.DoNothing(vm); } // what happens on cancel/close (optional) // raise dialog request event on the container

Lo prefiero de esta manera porque la mayoría de mis diálogos son controles pseudo-modales no bloqueantes y hacerlo de esta manera parece más sencillo que trabajar en torno a él. Prueba fácil de unidad también.


También compartí tu frustración. Estoy escribiendo una aplicación y tenía estos 3 requisitos:

  • Extensible
  • WPF con MVVM
  • Ejemplos compatibles GPL

Todo lo que encontré fueron fragmentos, así que comencé a escribirlo lo mejor que pude. Después de profundizar un poco, me di cuenta de que podría haber otras personas (como usted) que pudieran usar una aplicación de referencia, así que refactoreé los productos genéricos en un marco de aplicación WPF / MVVM y lo lancé bajo la LGPL. Lo llamé SoapBox Core . Si vas a la página de descargas, verás que viene con una pequeña aplicación de demostración, y el código fuente de esa aplicación de demostración también está disponible para su descarga. Espero que encuentres eso útil. Además, envíeme un correo electrónico a scott {at} soapboxautomation.com si desea más información.

EDITAR : También publicó un artículo de CodeProject que explica cómo funciona.