silverlight mvvm

Manejando estado de vista en Silverlight con MVVM



(4)

Me interesa saber cómo la gente maneja el estado de vista en una aplicación de Silverlight con el patrón MVVM. Digamos que tengo una máscara de búsqueda simple que llama asincrónicamente a un servicio web. Mientras la búsqueda está en progreso, me gustaría cambiar la GUI en consecuencia: - Deshabilitar el botón Buscar - Habilitar un botón Cancelar - etc.

Usando wpf podría crear un datatrigger que se una a alguna propiedad en el modelo de vista y luego haga los cambios a la interfaz gráfica de usuario. Ahora que no tengo un datatrigger en Silverlight, ¿cuál sería la forma más sensata de lograr esto de manera similar al datatrigger (código limpio, en un lugar si es posible)?

( Publiqué una pregunta similar, pero estaba mal redactada )


La forma más práctica es usar el BusyIndicator desde Silverlight Toolkit , supongo. Como enmascara toda el área donde lo aplica, todos los botones se desactivan automáticamente.

Para un botón cancelar, tendría que editar la plantilla de BusyIndicator para colocarlo directamente al lado de la animación de carga, creo.

Simplemente vincularía la propiedad IsBusy del IsBusy a una propiedad correspondiente en su ViewModel que configurará antes de cargar y restablecerá cuando haya terminado.


Mi forma estándar de hacer esto es exponer una propiedad "ViewState" del modelo de vista (normalmente una enumeración). A continuación, la vista se enlaza a la propiedad y utiliza el gestor de estado visual para cambiar a estados visuales apropiados según la enumeración.

El DataStateSwitchBehavior de Expression Samples es un buen ejemplo de cómo realizar el cambio a estados visuales.

EDITAR En respuesta al comentario

En primer lugar, cuando se trata de VisualStates use Blend (nadie debe verse forzado a escribir tanto XAML a mano). Creo que incluso está en todas (¿la mayoría?) De las suscripciones de MSDN.

El uso de Visual States comienza con Visual State Manager

<VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="GroupOne"> <VisualState x:Name="Normal"/> <VisualState x:Name="Searching"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups>

Normalmente agregarías esto a layoutroot.

El administrador de estado visual consiste en una colección de StateGroups que a su vez consiste en una colección de VisualStates.

Los grupos mantienen estados mutuamente excluyentes organizados, ya que puede tener múltiples estados visuales activos en cualquier momento, pero solo un estado de cada grupo. El patrón estándar es tener un estado vacío llamado algo así como "Normal" o "Predeterminado" para ser utilizado apagar los otros estados. Un estado base básicamente.

En su caso, usted tendría un estado visual de "búsqueda" que contendría un guión gráfico que desactivaría varios botones, activaría animaciones ocupadas, etc.


Mi solución es similar a la de Graeme Bradbury, PERO no uso DataStateSwitchBehavior, porque si mi control X se coloca dentro de un panel de pestañas (o algo similar) y el estado cambia mientras estoy en otra pestaña, entonces obtendré una excepción (''elemento'' no encontrado ..). Se produce una excepción porque mi control X se descarga mientras estoy en otra pestaña y no se encuentran los elementos que deben actualizarse.

Así que esto es lo que hago:

En mi opinión, el modelo I tiene una propiedad VisualState que envía un mensaje de notificación cuando cambia un estado (utilizo MVVM light toolkit ):

private string visualState = XVisualStates.InitialState; public string VisualState { get { return visualState; } set { visualState = value; Messenger.Default.Send(new XStateChangedMessage(value)); } }

y en el código de Mi vista detrás me suscribo a una notificación:

public partial class XControl : UserControl { private string visualState = XVisualStates.InitialState; public XControl() { InitializeComponent(); //go to state when view is loaded Loaded += (s, e) => ChangeState(); //every time a view is loaded go to current state //change visual state when a notification is received Messenger.Default.Register<XStateChangedMessage>(this, state => { visualState = state.CurrentState; //save current state ChangeState(); }); } void ChangeState() { try { VisualStateManager.GoToState(this, visualState, true); //will throw an exception if current view is unloaded } catch { //NOTE: supress ''element'' not found errors if user navigated to another view and state changes } } }

y XStateChangedMessage es una clase simple:

public class XStateChangedMessage { public string CurrentState { get; private set; } public XStateChangedMessage (string currentState) { CurrentState = currentState; } }


1) Puede crear algo así como la propiedad IsEnabledSearch en el modelo de visualización y vincularlo a la propiedad IsEnabled o Visibility de Button (necesitará un Bool to Visibility Converter). La creación de nuevos estados visuales solo para eso no es muy eficiente, porque sus botones ya tienen todo tipo de estados visuales dentro para admitir este comportamiento.

2) Jounce mvvm framework tiene una implementación muy buena para soportar VisualStates de ViewModel; Jounce Visual State Manager