【问题标题】:MVVM show new window from VM when seperated projects分离项目时,MVVM 显示来自 VM 的新窗口
【发布时间】:2017-11-17 14:25:01
【问题描述】:

我的问题涉及创建一千零一个主题的东西, 如果我忽略了我的问题的答案,我很抱歉,但就我看来,没有人能真正回答我的问题。例如: Opening new window in MVVM WPF

如果您只使用一个 WPF 项目(包括模型、虚拟机和视图),答案是可以的,但是因为我正在学习如何以正确的方式实现 MVVM(并且我已多次阅读最佳实践是创建用于模型、视图模型和单独的 gui 项目的单独的类库(dll))在我看来似乎不起作用,因为如果我想创建像 IWindowService 这样的接口(在以前的 url 和 here 上进行了描述,这是不可能的访问 Window 或 Control 类,因为那时我应该引用 gui 项目,并且模式的整个目标被破坏了。

所以我的问题是如何从例如 MainViewModel 中显示一个新窗口(带有新视图模型),同时尊重松散耦合的 MVVM 原则和单独的项目。

我正在努力实现的更深入的示例:

我有以下结构:

模型(dll项目)
简介

VIEWMODEL(dll 项目)
主视图模型
添加ProfileViewModel

VIEW (WPF)(exe 项目)
主窗口
添加配置文件窗口

我打开 MainWindow,我想按下 AddProfile 按钮,然后 AddProfileWindow 需要显示附加的 AddProfileViewModel。

【问题讨论】:

  • 您可以使用Messenger发送一些OpenWindow消息,并在查看项目stackoverflow.com/questions/16993918/…订阅它
  • 我看过 Messenger 但它似乎有点矫枉过正。这对于视图模型之间的通信似乎很有用,所以 +1

标签: c# wpf design-patterns mvvm


【解决方案1】:
  • 在模型项目中定义IWindowService接口。
  • 从视图模型项目中引用模型项目。
  • 在 WPF 应用程序(视图)项目中实现IWindowService

然后该按钮应绑定到使用IWindowService 打开窗口的ICommand。像这样的:

public class MainWindowViewModel
{
    private readonly IWindowService _windowService;

    public MainWindowViewModel(IWindowService windowService)
    {
        _windowService = windowService;
        AddProfile = new DelegateCommand(() =>
        {
            _windowService.OpenProfileWindow(new AddProfileViewModel());
        });
    }

    public ICommand AddProfile { get; }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainWindowViewModel(new WindowService());
    }
}

public class WindowService : IWindowService
{
    public void OpenProfileWindow(AddProfileViewModel vm)
    {
        AddProfileWindow win = new AddProfileWindow();
        win.DataContext = vm;
        win.Show();
    }
}

【讨论】:

    【解决方案2】:

    我为此苦苦挣扎,发现@mm8 发布的答案以及其他一些帖子非常有帮助。我对必须为每个视图创建一个类(或类中的方法)的想法并不疯狂,所以我创建了自己的变体。这是我在尝试使用 MVVM 时使用 WPF 的第一个项目之一,因此我将其分享以防万一,并从更有经验的人那里获得反馈。

    public class WindowDialogService : IWindowDialogService
        {
            private static readonly Dictionary<Type, Type> viewModelPairs =
                new Dictionary<Type, Type>
                {
                    [typeof(DetailsViewModel)] = typeof(DetailsView)
                };
    
            public void ShowWindowDialog(IViewModelBase viewModel)
            {
                if (!viewModelPairs.TryGetValue(viewModel.GetType(), out Type viewType))
                {
                    throw new ArgumentException("View Model not mapped", nameof(viewModel));
                }
    
                if (viewType.GetConstructor(Type.EmptyTypes).Invoke(new object[] { }) is Window view)
                {
                    view.DataContext = viewModel;
                    view.Owner = Application.Current.MainWindow;
                    view.ShowDialog();
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2012-05-24
      • 2017-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      • 2018-04-15
      • 2012-01-27
      相关资源
      最近更新 更多