2011-05-06 13 views
6

Así que estoy trabajando en la aplicación MVVM & Estoy comenzando a poner un poco de brillo & polaco en la funcionalidad.Silverlight MVVM - Habilitar botones y propiedades de visibilidad

En el lado izquierdo de la página, estoy mostrando estos valores:

DateActivated 
DateCompleted 
DateTrialClosed 
DateAccountingClosed 

Si hay una fecha en el PP, estoy viendo en un bloque de texto. Si no lo hay, estoy mostrando un botón al usuario, diciendo "Activar orden de trabajo", "Orden de trabajo completo", etc. ...

Estoy vinculando la visibilidad de cada uno de estos 8 (4 bloques de texto, Botón 4) controla una propiedad única en mi ViewModel del tipo Windows.Visibility. En mi setter del SelectedWorkOrder, evalúo el valor actual de la propiedad SelectedWorkOrder.DateActivated (por ejemplo) y configuro las propiedades de visibilidad en consecuencia. Esto es un poco detallado para mí, pero está funcionando como se esperaba.

Mi siguiente paso es deshabilitar cualquier botón visible después del primero (la lógica es simple ... no puede hacer clic en el botón 2 hasta que se haya hecho clic en el botón 1. No se puede hacer clic en el botón 3 hasta que ambos 1 & 2 hizo clic) No estoy seguro de cuál es la mejor manera de implementar esto. Como un FYI sobre esto, ya tengo un convertidor de valor de boolToVisibility en mi proyecto ... No estoy seguro de que su implementación sea diferente a la que estoy haciendo ahora (vea el código de VM a continuación).

Actualmente tengo esto para mi XAML:

<TextBlock Text="Proposed:" /> 
<TextBlock Text="Activated:" /> 
<TextBlock Text="Eng Completed:" /> 
<TextBlock Text="Trial Close:" /> 
<TextBlock Text="Accounting Close:" /> 
<TextBlock Text="{Binding SelectedWorkOrder.EstimatedStartDate}" Visibility="{Binding ProposedVisibility}" /> 
<TextBlock Text="{Binding SelectedWorkOrder.DateActivated}" Visibility="{Binding ActivatedTextBlockVisibility}" /> 
<Button Content="Activate Work Order" Visibility="{Binding ActivatedButtonVisibility}" /> 
<TextBlock Text="{Binding SelectedWorkOrder.DateCompleted}" Visibility="{Binding EngineeringCompletedTextBlockVisibility}" /> 
<Button Content="Work Order Eng Complete" Visibility="{Binding EngineeringCompletedButtonVisibility}" /> 
<TextBlock Text="{Binding SelectedWorkOrder.DateClosed}" Visibility="{Binding TrialCloseTextBlockVisibility}" /> 
<Button Content="Close Work Order (Trial)" Visibility="{Binding TrialCloseButtonVisibility}" /> 
<TextBlock Text="{Binding SelectedWorkOrder.DateClosed}" Visibility="{Binding AccountingCloseTextBlockVisibility}" /> 
<Button Content="Close Work Order (Actual)" Visibility="{Binding AccountingCloseButtonVisibility}" /> 

Código VM:

if (_SelectedWorkOrder.DateActivated.ToShortDateString() != "1/1/0001") 
{ 
    ActivatedTextBlockVisibility = Visibility.Visible; 
    ActivatedButtonVisibility = Visibility.Collapsed; 
} 
else 
{ 
    ActivatedTextBlockVisibility = Visibility.Collapsed; 
    ActivatedButtonVisibility = Visibility.Visible; 
} 

(La fecha se establece en 1/1/0001 en mi capa de acceso a la base de datos como estoy crear instancias de un nuevo DateTime si Is DBNull.Value = true)

+2

recomiendo encarecidamente el uso de [ 'DateTime.MinValue'] (http://msdn.microsoft.com/en-us/library/system.datetime.minvalue.aspx) en lugar de lanzar DateActivated a una cadena y compararla con "1/1/0001". –

Respuesta

2

Tuve un problema similar esta tarde :-)

Creo que la mejor manera de hacer este tipo de cosas es la visibilidad vinculante de una propiedad en ViewModel.

Puede usar un convertidor para cada una de estas variables (para que pueda devolver Visibility.Collapsed o Visibility.Visible when expected ;-)).

Puede usar el método "CanExecute" para cada uno de estos botones, por lo que el botón 2 no se puede ejecutar hasta que se presione el botón 1 (con una variable booleana, por ejemplo). Tiene que usar comandos para esto, de modo que el código asociado a cada botón estará en ModelView.

Si necesita ejemplos, puedo pegarlos en mi trabajo el lunes :-).

Un pequeño ejemplo codificándolo aquí directamente (no tengo Silverlight instalado aquí).

Su punto de vista debería ser así:

<Button Content="Activate Work Order" Command="{Binding ActivateWorkOrderCommand}" /> 

Puede buscar ejemplos de cómo usar los comandos en MVVM, aquí se tiene una simple example.

Para los convertidores, si todavía prefiere ocultar y mostrar los botones, se debe declarar una nueva clase que implementa IValueConverter:

public class UniversalConverter : IValueConverter { 
     public object Convert(object value, Type targetType, 
         object parameter, CultureInfo culture) { 
if(_SelectedWorkOrder.DateActivated.ToShortDateString() != "1/1/0001") 
{ 
      return Visibility.Collapsed; 
     } 
else { return Visibility.Visible; 
} 

Así que su punto de vista debería vincular el convertidor también:

<Button Content="Activate Work Order" Visibility="{Binding DateActivated, Converter={StaticResource DateConverter}}" /> 

Espero que esto te ayude ;-)

+0

Sí, los ejemplos serían geniales. Mi ViewModelBase ya está implementando iCommand e iNotify (no puedo recordar qué interfaz tiene CanExecute), así que no debería ser difícil. Simplemente no estoy seguro de cómo desencadenarlo, ya que nunca he usado ese método. Gracias amigo. –

+0

Voy a buscar un poco para encontrar algunos ejemplos, estoy en tiempo de relax :-P – zapico

+0

Gracias, voy a echar un vistazo. Definitivamente estoy familiarizado con el uso de comandos, y ya tengo un convertidor en su lugar. Simplemente no estoy seguro de que sea menos detallado que mi código ahora, aunque puedo ver que su propia clase es mejor para la reutilización del código. –

1

Aquí va un pequeño ejemplo.

Es un ejemplo simple para iniciar sesión cuando hace clic en un botón y cierra sesión cuando hace clic en otro.

Estos son los comandos:

 #region Login Command 

     public ViewModelCommand LoginCommand { get; set; } 

     public void Login(object parameter) 
     { 
      Code.Session.Session.Sesion.Logged = true; 
     } 

     public bool CanLogin(object parameter) 
     { 
      return !Code.Session.Session.Sesion.Logged; 
     } 
     #endregion 



     #region Logout Command 

     public ViewModelCommand LogoutCommand { get; set; } 

     public void Logout(object parameter) 
     { 
      Code.Session.Session.Sesion.Logged = false; 
     } 

     public bool CanLogout(object parameter) 
     { 
      return Code.Session.Session.Sesion.Logged; 
     } 
     #endregion 

Para obligar a la visibilidad y otros datos, declarar una propiedad:

const string pública SesionPropertyName = "Sesión";

private Model.Sesion _Sesion = Code.Session.Session.Sesion; 

public Model.Sesion Sesion 
{ 
    get 
    { 
     return _Sesion; 
    } 

    set 
    { 
     if (_Sesion == value) 
     { 
      return; 
     } 

     var oldValue = _Sesion; 
     _Sesion = value; 

     // Update bindings, no broadcast 
     RaisePropertyChanged(SesionPropertyName); 
    } 
} 

En este ejemplo, necesitamos botón para ocultar cuando se registra el usuario y mostrar cuando el usuario no está, así que hicimos este convertidor:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if ((bool)value) 
      { 
       return Visibility.Collapsed; 
      } 
      else 
      { 
       return Visibility.Visible; 
      } 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if ((Visibility)value == Visibility.Visible) 
      { 
       return false; 
      } 
      else 
      { 
       return true; 
      } 
     } 

Por último, tenemos que obligar a la ver, prestar atención al convertidor:

<Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="221*" /> 
       <ColumnDefinition Width="140*" /> 
      </Grid.ColumnDefinitions> 
      <Button Content="Logout" Grid.Column="1" HorizontalAlignment="Stretch" Margin="2" Name="bLogout" VerticalAlignment="Stretch" Command="{Binding LogoutCommand}" /> 
      <TextBlock Height="Auto" HorizontalAlignment="Stretch" Margin="2" Name="txtBlockUser" Text="{Binding Sesion.UserName}" VerticalAlignment="Center" TextWrapping="NoWrap" TextAlignment="Center" /> 
      <Grid Grid.ColumnSpan="2" > 
        <Button Content="Login" Command="{Binding LoginCommand}" Visibility="{Binding Sesion.Logged, Converter={StaticResource InverseBooleanVisibilityConverter}}"></Button> 
      </Grid> 
     </Grid> 
+0

Así que ya llegué a este punto; lo que no sé es qué debería hacer con la propiedad habilitada/deshabilitada. –

+0

Si tiene botones, se habilitarán/deshabilitarán debido al método canexecute. Debe llamar al método OnCanExecuted cuando crea que puede cambiar (por ejemplo, en el conjunto de propiedades): this.LoginCommand.OnCanExecuteChanged(); – zapico

Cuestiones relacionadas