更改视图 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
}

更改视图 WPF MVVM

双击一行时如何更改视图

首先,您需要为 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,它是显示所选视图所需的关键元素。