¿Enlazar el estado de visualización a un modelo de vista MVVM?

¿Cómo se vincula el estado VisualStateManager de un control a una propiedad en su modelo de vista? Se puede hacer?

En realidad puedes. El truco consiste en crear una propiedad adjunta y agregar una callback con propiedad que en realidad llame a GoToState :

 public class StateHelper { public static readonly DependencyProperty StateProperty = DependencyProperty.RegisterAttached( "State", typeof( String ), typeof( StateHelper ), new UIPropertyMetadata( null, StateChanged ) ); internal static void StateChanged( DependencyObject target, DependencyPropertyChangedEventArgs args ) { if( args.NewValue != null ) VisualStateManager.GoToState( ( FrameworkElement )target, args.NewValue, true ); } } 

A continuación, puede establecer esta propiedad en usted xaml y agregar un enlace a su viewmodel como cualquier otro:

    

Name y el State son propiedades regulares en el modelo de vista. Cuando Name se establece en el modelo de vista, ya sea por el enlace u otra cosa, puede cambiar el State que actualizará el estado visual. State también podría establecerse mediante cualquier otro factor y, aun así, actualizaría el estado de la vista en el cuadro de texto.

Dado que estamos usando un enlace normal para vincularnos al estado, podemos aplicar conversores o cualquier otra cosa que normalmente podríamos hacer, por lo que el modelo de vista no tiene que ser consciente de que está configurando un nombre de estado visual, estado. podría ser un bool o una enumeración o lo que sea.

También puede usar este enfoque utilizando wpftoolkit en .net 3.5, pero debe convertir el target en Control lugar de FrameworkElement .

Otra nota rápida sobre los estados visuales, asegúrese de no nombrar sus estados visuales para que entren en conflicto con los integrados a menos que sepa lo que está haciendo. Esto es especialmente cierto para la validación ya que el motor de validación intentará establecer sus estados cada vez que se actualice el enlace (y en otros momentos también). Vaya aquí para obtener una referencia sobre nombres de estado visuales para diferentes controles.

Soy nuevo en WPF, pero después de torcer los estados a través de capas MVVM de maneras extrañas durante algún tiempo finalmente encontré una solución con la que estoy contento. Cambie el estado como parte de la lógica de ViewModel y escúchelo en la vista XAML. No hay necesidad de convertidores o código detrás de métodos de “puenteo” o “me gusta”.

Ver código detrás del constructor

 // Set ViewModel as the views DataContext public ExampleView(ExampleViewModel vm) { InitializeComponent(); DataContext = vm; } 

Espacios de nombres XAML

 // Reference expression namespaces xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 

Enlaces XAML

 // Bind GoToStateAction directly to a ViewModel property      

Código de ViewModel

 // Update property as usual private string _state; public string State { get { return _state; } set { _state = value; NotifyPropertyChanged("State"); } } 

Ahora establecer la propiedad de estado de ExampleViewModel activará un cambio de estado correspondiente en la vista. Asegúrese de que los estados visuales tengan nombres que correspondan con los valores de las propiedades de estado o compárelos con enumeraciones, convertidores, etc.

Lea este artículo: Silverlight 4: usando VisualStateManager para animaciones de estado con MVVM

Alternativamente, si está justo después de cambiar entre dos estados, puede usar DataStateBehaviour . Lo he usado para cambiar el fondo cuando se muestra la página de inicio de sesión.

Espacios de nombres

 xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 

XAML

    

Esto se hace aún más simple mediante el uso de un marco como Caliburn.Micro .

Aquí hay una clase que uso para el soporte MVVM de los estados de VisualStateManager en WPF:

 public static class MvvmVisualState { public static readonly DependencyProperty CurrentStateProperty = DependencyProperty.RegisterAttached( "CurrentState", typeof(string), typeof(MvvmVisualState), new PropertyMetadata(OnCurrentStateChanged)); public static string GetCurrentState(DependencyObject obj) { return (string)obj.GetValue(CurrentStateProperty); } public static void SetCurrentState(DependencyObject obj, string value) { obj.SetValue(CurrentStateProperty, value); } private static void OnCurrentStateChanged(object sender, DependencyPropertyChangedEventArgs args) { var e = sender as FrameworkElement; if (e == null) throw new Exception($"CurrentState is only supported on {nameof(FrameworkElement)}."); VisualStateManager.GoToElementState(e, (string)args.NewValue, useTransitions: true); } } 

En tu XAML:

  ... 
Intereting Posts