2010-02-23 7 views
7

Me interesa saber cómo su gente maneja el estado de vista en una aplicación 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 que la búsqueda está en curso, me gustaría cambiar la interfaz gráfica de usuario en consecuencia: - Desactivar el botón de búsqueda - Activar un botón Cancelar - etcManejando el estado de la vista en Silverlight con MVVM

El uso de WPF que podría crear un DataTrigger que se une a alguna propiedad en el modelo de vista y luego realiza los cambios en la GUI. Ahora, dado 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)?

(I posted a similar question, but it was worded poorly)

Respuesta

7

Mi forma estándar de hacer esto es para 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 del 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 utilizar VisualStates Blend (nadie debe estar obligado a dejar que gran parte XAML con la mano). Creo que incluso está en todas (¿la mayoría?) De las suscripciones de MSDN.

mediante Visual Unidos comienza con Visual State Manager

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

Por lo general, esto agregaría a la 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 al mismo tiempo 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 entonces una "Búsqueda" estado visual que contendría un guión gráfico que desactivar varios botones, activar animaciones ocupadas etc.

+0

Entonces, ¿puedo definir los estados visuales en mi control (también en una ventana hija?) Y luego cambiarlos usando el DataStateSwitchBehavior? Por ejemplo, un estado podría ser 'SearchInProgress'. ¿Cómo puedo usar el VSM para desactivar el botón para que no se pueda hacer clic mientras el control está en 'SearchInProgress'? –

+0

Gracias Graeme. Lo hice funcionar en un proyecto de muestra y parece que este es el camino a seguir. Sin embargo, parece que me encontré con el mismo problema mencionado aquí: http://stackoverflow.com/questions/2118814/how-can-i-use-visualstates-in-a-childwindow. VSM no parece funcionar en ventanas secundarias. Ahora pondré todo en un UserControl y lo mencionaré en la ventana secundaria. Estoy usando el DataStateSwitcher que mencionaste para que sea impulsado por ViewModel. –

0

La forma más práctica es utilizar el BusyIndicator del Kit de herramientas de Silverlight Supongo. Como enmascara toda el área donde lo aplica, todos los botones se desactivan automáticamente.

Para un botón cancelar, debe editar la plantilla BusyIndicator para colocarla directamente junto a la animación de carga, creo.

Simplemente enlazará la propiedad IsBusy del BusyIndicator a la propiedad correspondiente en su ViewModel que configura antes de cargar y restablecer cuando haya terminado.

0

Mi solución es similar a Graeme Bradbury's, 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 aquí es lo que hago:

En mi modelo de vista que tienen una VisualState propiedad que envía un mensaje de notificación cuando un cambio de estado (yo uso 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; 
    } 
} 
0

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). Crear nuevos estados visuales solo para eso no es muy eficiente, porque sus botones ya tienen todo tipo de estados visuales adentro para soportar este comportamiento.

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

Cuestiones relacionadas