在 MVVM 中处理事件

Handling Events in MVVM

所以这是我的第一个 MVVM 应用程序。我有一个名为 MainWindowViewModel 的“shell”视图模型,用于主要 window,它基本上将视图分成两个页面:MainWindowRibbon 和 MainWindowFrame。 MainWindowViewModel 将两个页面都存储为属性,我计划使用数据绑定在 UI 中对其进行更新。以下是部分代码供参考:

MainWindowViewxaml~

<Grid>
    <Frame Content="{Binding MainWindowRibbon}" Grid.Column="0" Grid.Row="0"/>
    <ScrollViewer>
        <Frame Content="{Binding MainWindowFrame}"/>
    </ScrollViewer>
</Grid>

MainWindowView后面的代码~

    public partial class MainWindowView : Window
{
    public MainWindowView()
    {
        InitializeComponent();
        mainWindowViewModel = new MainWindowViewModel();
        DataContext = mainWindowViewModel;
    }
    public MainWindowViewModel mainWindowViewModel;
}

MainWindowViewModel代码~

        public MainWindowViewModel()
    {
        //MainWindowRibbon and MainWindowFrame are declared as public Page properties
        MainWindowRibbon = new MainWindowRibbonView();
        MainWindowFrame = new WelcomePageView();
    }

MainWindowRibbonView 和 MainWindowView 一样,实例化了 MainWindowRibbonViewModel。

当我希望在 MainWindowRibbonViewModel 中使用一个事件时,我的麻烦就来了,该事件将调用 MainWindowViewModel 重新分配 MainWindowFrame 页面。我不知道如何连接我在 MainWindowRibbonView 中创建的导航栏的按钮命令以在 MainWindowViewModel 中引起事件或更改。

我不知道我的组织方式是否理想。如果需要修改,请告诉我。

如果有人能帮助我确定最佳方法,或者只是一个有效的方法,我将不胜感激。

P.S。 抱歉,如果命名约定不是最好的。

编辑: 经验教训:听乔的话。

我想这取决于您在导航栏中使用的按钮类型。是 RadioButton 吗?一个RibbonToggleButton?它是绑定到 ICommand 的常规按钮吗?

由于您将导航栏称为“功能区”,我们假设它是一个 RibbonToggleButton(基本上仍然是一个复选框)。如果选中,您将显示一些 view-model 您的“第 1 页”。如果未选中,您应该另一个 view-model 代表您的“第 2 页”

我们还假设您的视图的功能区位于顶部。所以你有两行:功能区行和内容行。

我可能会重写您的 MainWindow 使其看起来像这样,(请注意 IsChecked 属性 到 view-model 中的某个布尔值 属性 就像这样:)

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>  <!-- The "Ribbon" -->
        <RowDefinition Height="*"/>     <!-- The page content -->
    </Grid.RowDefinitions>

    <ToggleButton Content="Show Page 1" IsChecked="{Binding ShowPage1}"/>

    <ScrollViewer Grid.Row=1>
        <Frame Content="{Binding CurrentViewModel}"/>
    </ScrollViewer>
</Grid>

我可能会这样写你的 view-model:(请注意,我假设它实现了 INotifyPropertyChanged 并且我调用了一个我没有显示的函数 RaisePropertyChanged

public class Page1ViewModel {}  // Fill this out with Page 1 properties
public class Page2ViewModel {}  // Fill this out with Page 2 properties

// MainWindowViewModel.  Implements INotifyPropertyChanged.  Implementation
// is not shown here.

public class MainWindowViewModel : INotifyPropertyChanged
{
    private Page1ViewModel = new Page1ViewModel();
    private Page2ViewModel = new Page2ViewModel();

    public MainWindowViewModel()
    {
        _currentViewModel = Page1ViewModel;
        ShowPage1 = true;
    }

    private object _currentViewModel;

    // The current contents of the main frame.

    public object CurrentViewModel 
    { 
        get => _currentViewModel;
        set
        {
            if (value == _currentViewModel)
                return;

            _currentViewModel = value;
            RaisePropertyChanged();
    }

    // Should CurrentViewModel be page 1 or page 2?

    public bool ShowPage1 
    { 
        get => return _currentViewModel == Page1ViewModel;
        set
        {
            if (value == ShowPage1)
                return;

            CurrentViewModel = value ? Page1ViewModel : Page2ViewModel;
            RaisePropertyChanged();
        }
    }
}

请注意,我没有向您展示 Page1VieModelPage2ViewModel 的任何属性,也没有向您展示隐含的 DataTemplates 我假设您会为它们编写。

我还假设您的导航栏(和一般的 MainWindowView)有一个 DataContext 已经设置为 MainWindowViewModel

使用命令按钮或 RadioButton 的实现会大不相同。