在 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();
}
}
}
请注意,我没有向您展示 Page1VieModel
或 Page2ViewModel
的任何属性,也没有向您展示隐含的 DataTemplate
s 我假设您会为它们编写。
我还假设您的导航栏(和一般的 MainWindowView
)有一个 DataContext
已经设置为 MainWindowViewModel
使用命令按钮或 RadioButton
的实现会大不相同。
所以这是我的第一个 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();
}
}
}
请注意,我没有向您展示 Page1VieModel
或 Page2ViewModel
的任何属性,也没有向您展示隐含的 DataTemplate
s 我假设您会为它们编写。
我还假设您的导航栏(和一般的 MainWindowView
)有一个 DataContext
已经设置为 MainWindowViewModel
使用命令按钮或 RadioButton
的实现会大不相同。