2010-04-16 18 views
7

Me estoy poniendo al día con MVVM, pero todos los ejemplos que he visto hasta ahora están vinculando controles de Vista a tipos de datos simples que no son de WPF, como cadenas y entradas. Sin embargo, en nuestra aplicación, quiero poder configurar el pincel de borde de un botón en función de un número en el Modelo.¿Dónde debería poner el código específico de WPF cuando uso MVVM?

Por el momento, traduzco el número en un pincel en ViewModel para mantener solo la vista XAML, pero ¿es así?

No me gusta poner código específico de WPF en el ViewModel, pero igualmente no me gusta la idea de poner código-detrás en mi panel de Vista.

¿Cuál es la mejor manera?

Gracias

Respuesta

7

Por el momento, traduzco el número en un pincel en el modelo de vista para mantener solo la vista XAML, pero ¿es así?

No, realmente no.

Idealmente, debe mantener las dependencias de WPF fuera de su ViewModel. Esto ayuda a permitir que su aplicación sea más comprobable, pero también fácilmente traducible a Silverlight u otras tecnologías en el futuro.

WPF proporciona un mecanismo para este escenario exacto, sin embargo: IValueConverter. Es muy fácil hacer un ValueConverter que convierte la traducción de un entero, cadena o cualquier otro tipo en un pincel. El Data Binding Overview muestra un ejemplo de traducción de un Color a un Pincel usando un Convertidor de valores.

Este es un diseño mucho mejor a largo plazo ... "Pinceles" y otros conceptos de WPF son realmente parte de la Vista, no están ligados a su lógica. Su ViewModel debe pensar en términos del estado , y su vista debe traducir ese estado a una forma específica de representar el estado.

Supongamos que quiere utilizar un pincel "rojo" para mostrar un error. En lugar de que ViewModel exponga un pincel, debería exponer algunas primitivas (es decir, una propiedad bool) como IsInErrorState. La Vista debería decidir cómo representar esto, ya sea a través de un pincel rojo, una gran advertencia, etc. Los convertidores permiten que esto suceda de una manera puramente XAML.


En su caso, el ValueConverter es fácil. Como va desde un Número -> Pincel (aunque recomendaría usar un Enum personalizado en lugar de un int), puede hacer algo como:

[ValueConversion(typeof(int), typeof(SolidColorBrush))] 
public class IntToBrushConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     int option = (int)value; 
     switch(option) 
     { 
      default: 
       return Brushes.Black; 
      case 1: 
       return Brushes.Red; 
      case 2: 
       return Brushes.Green; 
      // ... 
     } 

    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     // No need to convert back in this case 
     throw new NotImplementedException(); 
    } 
} 
+0

Pensando en esto más, estoy de acuerdo contigo. Ciertamente, algo como un Pincel no debe exponerse, porque un diseñador puede tener diferentes ideas sobre cómo se debe visualizar un estado en particular. Este es el tema más fundamental: exponer código específico de WPF generalmente significa que estaría exponiendo algunos detalles de la visualización, en lugar de un detalle del estado que debe visualizarse. Una máquina virtual está estrechamente acoplada a su vista, pero las responsabilidades aún deben estar claramente separadas. –

+0

Gracias Reed, justo lo que estaba buscando. – Surfbutler

2

encargo Try ValueConverter.

¿Cuál es el propósito de mantener su vista XAML solamente? Mantener ViewModel clean tiene sentido debido a la capacidad de prueba y SoC. Pero no hay código detrás?

+0

Leí en alguna parte que es una buena idea minimizar código subyacente en una vista, para minimizar el código específico de la plataforma (y también para ayudar con la prueba unitaria). Pero luego el problema fue cómo evitar que este código específico de WPF (en mi caso) contaminara la máquina virtual, de ahí la pregunta. Bien hecho por sugerir ValueConverter primero, para lo cual marqué su respuesta, pero la respuesta de Reed fue más detallada, así que le di el toque. ¡Gracias! – Surfbutler

+2

A medida que su aplicación crece, generalmente no es posible mantener el código detrás vacío.El manejo del enfoque y la personalización de algunos controles se relacionan más con el diseño que con el modelo, por lo que codebehind es un lugar natural para ellos. – majocha

+0

Ok, eso es interesante, estaba pensando que nunca podría poner ningún código subyacente en mi Vista al usar MVVM, pero es reconfortante saber que, al menos, piensas que no es necesario, ni siquiera posible. Gracias de nuevo. – Surfbutler

Cuestiones relacionadas