在MVVM WPF应用程序中,如何在视图模型之间传递应用程序状态?

6
我需要编写一个小程序来读取配置文件并生成报告。我希望最终能够使用MVVM,但它的入门有点棘手。哦,我正在使用Caliburn.Micro框架。
所以这就是我的情况,一个shell(主视图,用于承载其他视图),其中有一个带有3个按钮的ribbon:
1)打开文件 2)显示设置 3)显示结果
还有两个其他视图:SettingsView和ResultsView,分别带有生成和删除报告的按钮。
因此,我猜测视图结构将如下所示:
ShellView
   Ribbon
      OpenFileButton
      SettingsButton
      ResultsButton
   ContentControl (hosts SettingsView and ResultsView)

SettingsView
    CalculateResultsButton

ResultsView
    CancelResultsButton

这里的难点在于:
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.

请问我应该如何实现这个功能?我不知道应该采取什么样的策略。我的非MVVM思维认为,我应该创建一个状态变量,然后以某种方式将这些按钮绑定到该变量,但我想在MVVM世界中这不起作用,对吗?非常感谢您提供任何代码示例!
2个回答

1

由于您正在使用 CM,因此不需要任何代码后台。您可以删除 .xaml.cs 文件。

这是一个相当基本的示例,但它应该让您了解如何控制按钮的状态。在这个示例中,Open 将被启用,其他两个将被禁用。如果单击 Open,则会启用 Settings。一旦单击 Settings,就会发生相同的情况,Results 也会变为可用。

如果您需要进行全局状态管理,则可以通过将单例 SharedViewModel 注入到 ViewModel 中,然后在 CanXXX 方法中检查 SharedViewModel 中的值来实现。是一个演示不同事物的 SL 演示文稿之一,其中一个是注入单例以共享数据,在 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

MVVM和WPF命令完美地满足了您的“棘手部分”要求,因为它们内置了ICommand.CanExecute()方法,该方法允许根据自定义逻辑启用/禁用相应的按钮。

要使用这个不错的功能,首先看一下RoutedCommand Class,然后在MSDN上查看自我说明的示例How to: Enable a Command(请参见下面的代码片段)。

而且关于MVVM,它真的很简单!只需尝试一下,您就会爱不释手;)简而言之-您必须为每个EntityView.xaml创建相应的EntityViewModel类,然后将其实例放入视图的DataContext中,可以在代码中显式地使用绑定:

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

MVVM命令和Command.CanExecute绑定:

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# 代码后台:

// 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);

不太理想。Caliburn Micro避免了所有的ICommand繁琐操作。http://caliburnmicro.codeplex.com/discussions/250844 - Phil Degenhardt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接