更改视图 WPF MVVM
本文关键字:MVVM WPF 视图 | 更新日期: 2023-09-27 18:30:27
我是WPF和MVVM的初学者,但想通过构建一些小项目来学习它。
我有一个使用 Model-View-ViewModel 模式的 WPF 应用程序,基于 Rachel Lim 示例。在我的应用程序中,我有 2 个视图 - 员工列表和员工详细信息。员工列表存储在 GidView 中。
我遇到的主要问题是
- 当我双击一行时如何更改视图,
- 如何从第一列 (employee_id) 获取值并将其传递到"员工详细信息"视图中。
基本导航采用 xaml 格式,带有 DataTmplate 和 ItmCntrol:
<Window.Resources>
<DataTemplate DataType="{x:Type local:HomeViewModel}">
<local:HomeView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:EmployeesListViewModel}">
<local:EmployeesListView />
</DataTemplate>
</Window.Resources>
<ItemsControl ItemsSource="{Binding PageViewModels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding }"
Margin="2,5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我也有应用程序视图模型,其中是视图列表
public class ApplicationViewModel : ObservableObject
{
#region Fields
private ICommand _changePageCommand;
private IPageViewModel _currentPageViewModel;
private List<IPageViewModel> _pageViewModels;
#endregion
public ApplicationViewModel()
{
// Add available pages
PageViewModels.Add(new HomeViewModel());
PageViewModels.Add(new EmployeesListViewModel());
PageViewModels.Add(new EmployeeDetailsViewModel());
// Set starting page
CurrentPageViewModel = PageViewModels[0];
}
#region Properties / Commands
public ICommand ChangePageCommand
{
get
{
if (_changePageCommand == null)
{
_changePageCommand = new RelayCommand(
p => ChangeViewModel((IPageViewModel)p),
p => p is IPageViewModel);
}
return _changePageCommand;
}
}
public List<IPageViewModel> PageViewModels
{
get
{
if (_pageViewModels == null)
_pageViewModels = new List<IPageViewModel>();
return _pageViewModels;
}
}
public IPageViewModel CurrentPageViewModel
{
get
{
return _currentPageViewModel;
}
set
{
if (_currentPageViewModel != value)
{
_currentPageViewModel = value;
OnPropertyChanged("CurrentPageViewModel");
}
}
}
#endregion
#region Methods
private void ChangeViewModel(IPageViewModel viewModel)
{
if (!PageViewModels.Contains(viewModel))
PageViewModels.Add(viewModel);
CurrentPageViewModel = PageViewModels
.FirstOrDefault(vm => vm == viewModel);
}
#endregion
}
双击一行时如何更改视图
首先,您需要为 MouseDoubleClick 事件添加 EventTrigger:
<DataGrid Name="gridEmployees" ItemsSource="{Binding Employees}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<local:CustomCommandAction Command="{Binding DoubleClickCommand}" CommandParameter="{Binding ElementName=gridEmployees, Path=SelectedItems[0]}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
CustomCommandAction 是一个类,它继承自 TriggerAction,用作视图模型中事件和命令之间的链接。这是代码:
public sealed class CustomCommandAction : TriggerAction<DependencyObject>
{
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object), typeof(CustomCommandAction), null);
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
"Command", typeof(ICommand), typeof(CustomCommandAction), null);
public ICommand Command
{
get
{
return (ICommand)this.GetValue(CommandProperty);
}
set
{
this.SetValue(CommandProperty, value);
}
}
public object CommandParameter
{
get
{
return this.GetValue(CommandParameterProperty);
}
set
{
this.SetValue(CommandParameterProperty, value);
}
}
protected override void Invoke(object parameter)
{
if (this.AssociatedObject != null)
{
ICommand command = this.Command;
if (command != null)
{
if (this.CommandParameter != null)
{
if (command.CanExecute(this.CommandParameter))
{
command.Execute(this.CommandParameter);
}
}
else
{
if (command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
}
}
}
}
之后,最简单的解决方案是在命令执行方法中使用 ChangeViewModel 方法,例如:
...
_doubleClickCommand = new RelayCommand(OnDoubleClick);
...
private RelayCommand _doubleClickCommand = null;
private ApplicationViewModel _applicationViewModel;
private void OnDoubleClick(object obj)
{
EmployeeDetailsViewModel selectedModel = obj as EmployeeDetailsViewModel;
_applicationViewModel.ChangeViewModel(selectedModel);
}
public ICommand DoubleClickCommand
{
get
{
return _doubleClickCommand;
}
}
如何从第一列 (employee_id) 获取值并将其传递到"员工详细信息"视图中
对于您的 DataGrid,您可以使用 EmployeeDetailsViewModel 的集合作为 ItemsSource。如果这样做,所选项将作为 EmployeeDetailsViewModel 的实例传递给命令 Execute 方法,您将能够从那里获取 Id。
看起来您缺少显示所选视图所需的元素。如果您查看链接的示例注释,则 ItemsControl 包含在边框中,而边框又位于 DockPanel 内。
在 DockPanel 下方有一个 ContentControl,它是显示所选视图所需的关键元素。