A través de la generosa ayuda en this question, armé la siguiente estructura MVVM que muestra los cambios de un modelo en tiempo real en XAML (fecha/hora actual), muy agradable.Modelos gordos, ViewModels delgados y Vistas tontas, el mejor enfoque MVVM?
Una ventaja fresco de esta configuración es que cuando nos fijamos en la vista en modo de diseño de Visual Studio o Blend, que ver la hora de relojería por, lo que significa que en el tiempo de diseño que tiene acceso a los datos en tiempo real de su modelo .
En el proceso de conseguir que esto funcione, me sorprendió ver la mayor parte del movimiento mayor de mi modelo de vista en mi modelo, incluida la aplicación de INotifyPropertyChange. Otro cambio es que I ya no se une a propiedades en el modelo de vista, pero a métodos.
Así Actualmente este es mi sabor favorito de MVVM:
View es tonto:
- uno ObjectDataProvider para cada objeto que necesita de su modelo
- cada ObjectDataProvider se asigna a un método en ViewModel (no en una propiedad)
- no x: propiedades de nombre en elementos XAML
modelo de vista es flaca:
- la única cosa en su modelo de vista son los métodos en que su visión se une
Modelo es la grasa:
- el modelo implementa INotifyPropertyChanged en cada una de sus propiedades.
- para cada método en su ViewModel (por ejemplo, GetCurrentCustomer) hay un método de singleton correspondiente en su modelo (por ejemplo, GetCurrentCustomer).
- el modelo se encarga de cualquier tiempo real enhebrar funcionalidad como en este ejemplo
Preguntas:
- Aquellos de ustedes que han estado implementando MVVM en escenarios reales, es la siguiente la estructura básica que también ha establecido, y si no, ¿cómo varía la suya?
- ¿Cómo ampliaría esto para incluir comandos enrutados y eventos enrutados?
El siguiente código funcionará si solo copia el XAML y el código de atrás en un nuevo proyecto de WPF.
XAML:
<Window x:Class="TestBinding99382.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestBinding99382"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<ObjectDataProvider
x:Key="DataSourceCustomer"
ObjectType="{x:Type local:ShowCustomerViewModel}"
MethodName="GetCurrentCustomer"/>
</Window.Resources>
<DockPanel DataContext="{StaticResource DataSourceCustomer}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding Path=LastName}"/>
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock Text="{Binding Path=TimeOfMostRecentActivity}"/>
</StackPanel>
</DockPanel>
</Window>
código subyacente:
using System.Windows;
using System.ComponentModel;
using System;
using System.Threading;
namespace TestBinding99382
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
//view model
public class ShowCustomerViewModel
{
public Customer GetCurrentCustomer() {
return Customer.GetCurrentCustomer();
}
}
//model
public class Customer : INotifyPropertyChanged
{
private string _firstName;
private string _lastName;
private DateTime _timeOfMostRecentActivity;
private static Customer _currentCustomer;
private Timer _timer;
public string FirstName
{
get
{
return _firstName;
}
set
{
_firstName = value;
this.RaisePropertyChanged("FirstName");
}
}
public string LastName
{
get
{
return _lastName;
}
set
{
_lastName = value;
this.RaisePropertyChanged("LastName");
}
}
public DateTime TimeOfMostRecentActivity
{
get
{
return _timeOfMostRecentActivity;
}
set
{
_timeOfMostRecentActivity = value;
this.RaisePropertyChanged("TimeOfMostRecentActivity");
}
}
public Customer()
{
_timer = new Timer(UpdateDateTime, null, 0, 1000);
}
private void UpdateDateTime(object state)
{
TimeOfMostRecentActivity = DateTime.Now;
}
public static Customer GetCurrentCustomer()
{
if (_currentCustomer == null)
{
_currentCustomer = new Customer
{ FirstName = "Jim"
, LastName = "Smith"
, TimeOfMostRecentActivity = DateTime.Now
};
}
return _currentCustomer;
}
//INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
En cuanto a RelayCommands y RoutedCommands, es posible que desee echar un vistazo a estas respuestas: http://stackoverflow.com/questions/650010/mvvm-routed-and-relay-command/6441472#6441472 – Marc