2009-04-20 11 views
6

actualizaciónWPF MVVM: Convención sobre la configuración para ResourceDictionary?

En el espíritu wiki de stackoverflow, aquí es una actualización:

I pinchos sugerencia IValueConverter de Joe White continuación. Funciona a las mil maravillas.

He escrito un ejemplo de "inicio rápido" de esto que automatiza el mapeo de ViewModels-> Vistas usando algún reemplazo de cadena económico. Si no se encuentra una vista que represente ViewModel, se establece de manera predeterminada en una página "En construcción". Estoy doblando este enfoque "WPF MVVM White" ya que fue idea de Joe White. Aquí hay un par de capturas de pantalla.

La primera imagen es un caso de "[SomeControlName] ViewModel" tiene una "[SomeControlName] View" correspondiente, basada en la convención de nomenclatura pura. El segundo es un caso en el que ModelView no tiene vistas para representarlo. No más ResourceDictionaries con vistas largas de ViewModel to View. Es una convención de nomenclatura pura ahora.

Wpf Mvvm White

he publicado una descarga del proyecto aquí: Mvvm.White.Quickstart.zip


Post original

leí de fantastic MSDN article Josh Smith en WPF MVVM el fin de semana. Está destinado a ser un clásico de culto.

Me tomó un tiempo entender la magia de pedirle a WPF que muestre ViewModel.

Es como decir "Aquí hay una clase, WPF. Ve a descubrir qué UI usar para presentarla".

Para quienes se perdieron esta magia, WPF puede hacer esto mirando el Ver para modelview en el mapeo ResourceDictionary y sacando el correspondiente Ver. (Desplácese hacia abajo hasta Figure 10 Supplying a View).

Lo primero que salta a mí inmediatamente es que ya hay una fuerte convención de nombres de:

classNameView ("View" suffix) 
classNameViewModel ("ViewModel" suffix) 

Mi pregunta es:

Desde el ResourceDictionary se puede manipular mediante programación, I "m preguntándose si alguien ha logrado Regex. Reemplazar todo, , por lo que la búsqueda es automática, y cualquier nueva vista/vista Modeles se resuelven en virtud de su convención de nomenclatura?

[Editar] Lo que estoy imaginando es un gancho/intercepción en ResourceDictionary.

...Considerando también un método en el arranque que utiliza interoperabilidad de sacar *View$ y *ViewModel$ nombres de clase para crear el diccionario DataTemplate en código:

//build list 
foreach .... 
    String.Format("<DataTemplate DataType=\"{x:Type vm:{0} }\"><v:{1} /></DataTemplate>", ...) 
+0

Oh, sí que el artículo es genial. Uso su RelayCommand en cada proyecto, excepto que agregué una propiedad Nombre y Descripción para el enlace de una sola vez de cosas como el texto del botón y la información sobre herramientas. – Botz3000

+0

Existe un marco MVVM (he visto tantos que me olvido de cómo se llamaba) que hace exactamente lo que usted está hablando. Como recuerdo, se utiliza la convención de nombre para conectar automáticamente las vistas a sus modelos de vista. Lo odiaba. Parecía magia negra. Cuando miras el código, nunca puedes decir cómo se conectan las piezas. Me gusta definir las plantillas de datos de mi vista en contexto algunas veces para que quede muy claro cómo se asocia el modelo de vista/vista. –

+1

El [enlace del proyecto] (http://rootsilver.com/files/Mvvm.White.Quickstart.zip) está fuera de servicio. ¿Podrías volver a cargar a otro lugar? –

Respuesta

17

En lugar de escribir código para agregar explícitamente cosas a la ResourceDictionary, ¿qué acaba de generar la derecha ver a pedido? Puedes hacer esto con un ValueConverter.

Sus recursos se vería así:

<Views:ConventionOverConfigurationConverter x:Key="MyConverter"/> 
<DataTemplate DataType="{x:Type ViewModels:ViewModelBase}"> 
    <ContentControl Content="{Binding Converter={StaticResource MyConverter}}"/> 
</DataTemplate> 

usted todavía necesita un recurso DataTemplate, pero siempre y cuando sus ViewModels todos tienen una clase base común, lo único que necesita una DataTemplate a cuidar de todos de ellos.

definir la clase de convertidor de valores:

public class ConventionOverConfigurationConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, 
     CultureInfo culture) 
    { 
     // value is the ViewModel. Based on its GetType(), build a string 
     // with the namespace-qualified name of the view class, then: 
     return Activator.CreateInstance(Type.GetType(viewName)); 
    } 
    public object ConvertBack(object value, Type targetType, 
     object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 

Todo lo que se necesita hacer es escribir la lógica dentro del convertido, el cual dependerá de cosas como si sus puntos de vista y ViewModels están en el mismo espacio de nombres o no .

+0

que, señor, ¡es exactamente lo que quiero hacer! =) –

+0

Gracias Joe - He actualizado esta pregunta en función de sus comentarios. –

+0

¡Excelente! Eso ha cortado mi App.xaml de unos pocos cientos de líneas a unas pocas decenas :) – Grokys

-1

decidí a hacer más o menos lo mismo hthe por lo cargo mis DataTemplates directamente en el ResourceDictionary usando

private void RegisterResources() 
    { 
     ResourceDictionary dictionary = new ResourceDictionary(); 
     dictionary.Source = new Uri("pack://application:,,,/StartupModule;Component/UIResources.xaml"); 
     Application.Current.Resources.MergedDictionaries.Add(dictionary); 
    } 

donde el archivo UIResources es un archivo xamls ResourceDictionary que contiene todos nuestros DataTemplates