2012-04-04 9 views
6

Necesito escribir una pequeña aplicación para leer un archivo de configuración y generar algún informe con él. Esperaba finalmente usar MVVM, pero es bastante complicado comenzar. Oh, estoy usando Caliburn.Micro framework.Pasar el estado de la aplicación entre viewmodels en la aplicación MVVM WPF

Así que esto es lo que tengo, una concha (vista principal que aloja otros puntos de vista) que tiene una cinta con 3 botones en él:

1) Abrir el archivo 2) Mostrar ajustes 3) Mostrar resultados

Y otras dos vistas, SettingsView y ResultsView con botones para generar y eliminar un informe.

así que supongo que la estructura vista sería así:

ShellView 
    Ribbon 
     OpenFileButton 
     SettingsButton 
     ResultsButton 
    ContentControl (hosts SettingsView and ResultsView) 

SettingsView 
    CalculateResultsButton 

ResultsView 
    CancelResultsButton 

La parte difícil es la siguiente:

1. "Show settings" button is disabled until a file is opened (via Open file). 
2. "Show results" button is disabled until a report is calculated (via a 
    method in SettingsViewModel). 
3. If a report is calculated, the CalculateResultsButton is disabled and 
    CancelResultsButton is enabled and vice versa. 

favor aconsejar cómo podría lograr esto? No tengo idea de qué estrategia debería elegir. Mi cerebro que no es de MVVM dice que debería crear una variable de estado y, de alguna manera, unir esos botones a esa variable, pero supongo que eso no funcionará en un mundo de MVVM, ¿verdad? ¡Cualquier ejemplo de código sería muy, muy muy apreciado!

¡Muchas gracias!

Respuesta

1

Dado que está utilizando CM no necesitará ningún código subyacente. Puede eliminar los archivos .xaml.cs si lo desea.

Este es un ejemplo bastante básico pero debería darle una idea sobre cómo controlar el estado de los botones. En este ejemplo, Open se habilitará y los otros dos estarán deshabilitados. Si hace clic en Open, Settings está habilitado. Lo mismo ocurre con Results una vez que se hace clic en Settings.

Si necesita una forma de hacer un estado global, se puede aplicar el mismo concepto inyectando un singleton, SharedViewModel, en ViewModels y los métodos CanXXX pueden verificar los valores en SharedViewModel. This es una demostración SL de diferentes cosas, pero una está inyectando un singleton para compartir datos, la misma idea se aplica en wpf.

ShellView:

<Window x:Class="CMWPFGuardSample.ShellView" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

    <Grid Background="White"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 
     <StackPanel Grid.Row="0" 
        Orientation="Horizontal"> 
      <Button x:Name="Open" 
        Content="Open" /> 
      <Button x:Name="Settings" 
        Content="Settings" /> 
      <Button x:Name="Results" 
        Content="Results" /> 
     </StackPanel> 
    </Grid> 

</Window> 

ShellViewModel:

[Export(typeof (IShell))] 
    public class ShellViewModel : PropertyChangedBase, IShell 
    { 
     private bool _isOpen; 
     public bool IsOpen 
     { 
      get { return _isOpen; } 
      set 
      { 
       _isOpen = value; 
       NotifyOfPropertyChange(() => IsOpen); 
       NotifyOfPropertyChange(() => CanSettings); 
      } 
     } 

     private bool _isSettings; 
     public bool IsSettings 
     { 
      get { return _isSettings; } 
      set 
      { 
       _isSettings = value; 
       NotifyOfPropertyChange(() => IsSettings); 
       NotifyOfPropertyChange(() => CanResults); 
      } 
     } 

     public bool IsResults { get; set; } 

     public void Open() 
     { 
      IsOpen = true; 
     } 

     public bool CanSettings 
     { 
      get { return IsOpen; } 
     } 

     public void Settings() 
     { 
      IsSettings = true; 
     } 

     public bool CanResults 
     { 
      get { return IsSettings; } 
     } 

     public void Results() 
     { 
     } 
    } 
0

Los comandos de MVVM y WPF se adaptan perfectamente a sus requisitos de "parte complicada" ya que han incorporado el método ICommand.CanExecute() que permite habilitar/deshabilitar el botón correspondiente según la lógica personalizada.

Para usar esta función de navegación, primero eche un vistazo al ejemplo RoutedCommand Class y se explica por sí mismo en MSDN How to: Enable a Command (consulte los fragmentos de código a continuación).

Y, en general, sobre MVVM, ¡es realmente SIMPLE! Haga la prueba y no se deje sin ella;) En pocas palabras - usted tiene que crear para cada EntityView.xaml correspondiente EntityViewModel clase y luego sólo hay que poner ejemplo de ello en la vista DataContext ya sea explícitamente en el código o el uso de fijaciones:

var entityViewModel = new EntityViewModel(); 
var view = new EntityView(); 
view.DataContext = entityViewModel; 

comando MVVM y Command.CanExecute fijaciones:

XAML:

<Window x:Class="WCSamples.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="CloseCommand" 
    Name="RootWindow" 
    > 
    <Window.CommandBindings> 
    <CommandBinding Command="ApplicationCommands.Close" 
        Executed="CloseCommandHandler" 
        CanExecute="CanExecuteHandler" 
        /> 
    </Window.CommandBindings> 
    <StackPanel Name="MainStackPanel"> 
    <Button Command="ApplicationCommands.Close" 
      Content="Close File" /> 
    </StackPanel> 
</Window> 

C# código detrás:

// Create ui elements. 
StackPanel CloseCmdStackPanel = new StackPanel(); 
Button CloseCmdButton = new Button(); 
CloseCmdStackPanel.Children.Add(CloseCmdButton); 

// Set Button's properties. 
CloseCmdButton.Content = "Close File"; 
CloseCmdButton.Command = ApplicationCommands.Close; 

// Create the CommandBinding. 
CommandBinding CloseCommandBinding = new CommandBinding(
    ApplicationCommands.Close, CloseCommandHandler, CanExecuteHandler); 

// Add the CommandBinding to the root Window. 
RootWindow.CommandBindings.Add(CloseCommandBinding); 
+0

No es ideal. Caliburn Micro evita todo el guante de ICommand. http://caliburnmicro.codeplex.com/discussions/250844 –

Cuestiones relacionadas