首页 > 解决方案 > 根据使用 MVVM 从视图模型读取的数据库打开视图选择

问题描述

在我的 WPF MVVM 项目中,我有一些表单和一个保存员工信息的数据库。有一个员工视图模型,这有一个employeeId传递给它,使用员工模型,员工的详细信息是从数据库中读取的。这也会读取员工是“用户”还是“管理员”。

然后视图模型将决定加载哪个视图。用户视图或管理员视图。这两个视图之间有很多相似之处,这就是为什么我对两者都使用相同的视图模型。

这就是为什么对于我的项目,我决定保持一致并让我的视图模型打开它们的视图。但是,在网上研究我只能看到实例化视图的建议,然后在视图构造函数中创建视图模型。

我的方法是 MVVM 的错误方法吗?我将如何以正确的方式处理这种情况?

主窗口视图模型

    public void OpenSelectedEmployee(object employee)
    {
        if (employee == null)
            return;

        StaffListModel model = (StaffListModel)employee;

        EmployeeViewModel vm = new EmployeeViewModel(model.EmployeeId);
    }

员工视图模型

    private EmployeeModel employee;
    private Window employeeWindow;
    
    // Employee View Model Constructor
    public EmployeeViewModel(int employeeId)
    {
        // Connect to DB and read data for employee class
        if (LoadEmployee(employeeId))
        {
            if (employee.UserType == "User")
                employeeWindow = new EmployeeUserDetailsView();
            else // if Admin
                employeeWindow = new EmployeeAdminDetailsView();
            
            employeeWindow.DataContext = this;
            employeeWindow.ShowDialog();
        }
        else
        {
            // Open error message
            MessageBox.Show("Error loading employee occurred");
        }
    }

我已经考虑将用户类型存储在主窗口视图模型中,以便决定打开哪个视图。但是,如果由于某种原因数据库无法读取员工 ( LoadEmployee(employeeId)),则创建视图毫无意义,我希望显示错误消息框。

编辑:这是LoadEmployee目前的方法EmployeeViewModel。它在构造函数中使用,并通过绑定按钮刷新表单。

    public bool LoadEmployee(int employeeId)
    {
        if (!DbConnector.OpenDB())
            return false;

        try
        {
            employee = EmployeeModel.FindById(employeeId);
            Depots = DepotModel.FindAllShort();
            Departments = EmployeeModel.FindAllDepartments();
            TenureHistory = TenureHistoryModel.FindAllByEmployeeId(employeeId);
            IdCards = IdCardModel.FindAllByEmployeeId(employeeId);
            Qualifications = QualificationModel.FindAllByEmployeeId(employeeId);
            TheoryBookings = TheoryBookingModel.FindAllByEmployeeId(employeeId);
            MedicalRecords = MedicalRecordModel.FindAllByEmployeeId(employeeId);
            EyesightChecks = EyesightCheckModel.FindAllByEmployeeId(employeeId);
        }
        catch
        {
            DbConnector.CloseDB();
            return false;
        }

        DbConnector.CloseDB();
        return true;
    }
    public void Refresh(object parameter)
    {
        if (!LoadEmployee(employee.EmployeeId))
            MessageBox.Show("An error has occurred");

        NotifyPropertyChanged(string.Empty);
    }

标签: c#wpfmvvm

解决方案


从视图模型创建或引用视图或窗口违反并有效地破坏了 MVVM 设计模式。

您应该为您注入MainWindowViewModel一个IWindowService负责创建窗口的实现:

public class WindowService : IWindowService
{
    public void ShowDialog(EmployeeViewModel viewModel, EmployeeModel model)
    {
        if (LoadEmployee(model.employeeId))
        {
            Window employeeWindow;
            if (model.UserType == "User")
                employeeWindow = new EmployeeUserDetailsView();
            else // if Admin
                employeeWindow = new EmployeeAdminDetailsView();

            employeeWindow.DataContext = viewModel;
            employeeWindow.ShowDialog();
        }
        else
        {
            // Open error message
            MessageBox.Show("Error loading employee occurred");
        }
    }
}

主窗口视图模型:

private readonly IWindowService _windowService;

public MainWindowViewModel(IWindowService windowService)
{
    _windowService = windowService;
}

public void OpenSelectedEmployee(object employee)
{
    if (employee == null)
        return;

    StaffListModel model = (StaffListModel)employee;

    EmployeeViewModel vm = new EmployeeViewModel(model.EmployeeId);

    _windowService.ShowDialog(vm, model);
}

在此处查看我的答案以获取另一个示例。


推荐阅读