【问题标题】:WPF MVVM - how to inject a service into the ViewModelWPF MVVM - 如何将服务注入 ViewModel
【发布时间】:2020-01-23 03:37:14
【问题描述】:

我是 WPF 和 MVVM 的新手,我需要创建一个简单的对话框功能,允许我在屏幕上弹出确认消息,例如“确认删除?” y/n 按钮。我为此创建了一个对话服务(本质上是一个简单的 System.Windows.MessageBox 包装器),我想在整个应用程序中使用它。据我了解,我应该通过我的所有 ViewModel 的构造函数注入这个服务,如下所示:

public MainWindowViewModel(IDialogService injectedDialogService) // Dialog service dependency injection
{
    dialogService = injectedDialogService;
    ...
    ...
}

我在各自的 ViewModel 中将 dialogService 声明为:

 private IDialogService dialogService;

然后我希望像这样在整个 ViewModel 中使用它:

dialogService.ShowDialog("Some message...");

或者,像这样:

if (dialogService.ShowDialog("Confirm delete?", "Confirmation",  DialogButtons.YesNo) == DialogResult.Yes)
{
    // Delete it...
}

但是,我从各自的视图中收到以下投诉:

“MainWindowViewModel”类型不包括任何可访问的构造函数。

当我编译解决方案时,来自视图的以下错误消息:

System.NullReferenceException: '对象引用未设置为对象的实例。'

这就是我将 View 与 ViewModel 关联起来的方式:

<Window.Resources>
        <vm:MainWindowViewModel x:Key="MainWindowViewModel"/>
        ...
        ...
        ...
</Window.Resources>

还有数据上下文:

<Window.DataContext>
        <vm:MainWindowViewModel/>
</Window.DataContext>

如果这有帮助,这里是我的对话服务:

namespace FIM.Framework.Services
{
    public enum DialogButtons
    {
        OK = 0,
        OKCancel = 1,
        YesNoCancel = 3,
        YesNo = 4,
    }

    public enum DialogResult
    {
        None = 0,
        OK = 1,
        Cancel = 2,
        Yes = 6,
        No = 7,
    }

    public enum DialogImage
    {
        None = 0,
        Error = 16,
        Hand = 16,
        Stop = 16,
        Question = 32,
        Exclamation = 48,
        Warning = 48,
        Information = 64,
        Asterisk = 64,
    }

    public interface IDialogService
    {
        DialogResult ShowDialog(string messageBoxText, 
                                        string caption = null,
                                        DialogButtons buttons = DialogButtons.OK,
                                        DialogImage icon = DialogImage.None,
                                        DialogResult defaultResult = DialogResult.None);
    }

    public class DialogService : IDialogService
    {
        public DialogResult ShowDialog(string messageBoxText, 
                                       string caption = null, 
                                       DialogButtons buttons = DialogButtons.OK, 
                                       DialogImage image = DialogImage.None, 
                                       DialogResult defaultResult = DialogResult.None)
        {
            return (DialogResult)System.Windows.MessageBox.Show(messageBoxText, 
                                                                caption,
                                                                (System.Windows.MessageBoxButton)buttons,
                                                                (System.Windows.MessageBoxImage)image,
                                                                (System.Windows.MessageBoxResult)defaultResult);
        }
     }
}

你能帮我解决这个问题吗?如果我的方法是错误的,或者不是最好的,有人可以建议一个更好的对话服务实现吗? 非常感谢。

【问题讨论】:

  • 取决于框架,有些是约定俗成的。
  • 我不使用任何 MVVM 框架,例如 Caliburn 或 MVVM light,如果这就是你的意思的话。我正在尝试自己实现 MVVM 框架。

标签: wpf mvvm modal-dialog


【解决方案1】:

由于您的 MainWindowViewModel 需要一个参数,因此您无法在 xaml 中实例化它。您需要在 App.xaml 文件的代码隐藏中覆盖 OnStartup()


  1. 在 App.xaml 中删除 StartupUri="MainWindow.xaml"
  2. 在 App.xaml 的代码隐藏中,覆盖 OnStartup(StartupEventArgs e):

protected override void OnStartup(StartupEventArgs e)
{
     base.OnStartup(e);

     var viewmodel = new MainWindowViewModel(new DialogService());
     var window = new MainWindow { DataContext = viewmodel };
     window.Show();
 }

【讨论】:

  • 感谢科斯塔斯的帮助。我认为我必须将其应用于我的所有观点。与此同时,我将它添加到我的 ViewModelBase 类中,它在我所有的视图模型中都可以正常工作:public virtual IDialogService DialogService { get { return new DialogService(); } } 有了这个,我只需使用这个具体的实现:DialogService.ShowMessage("Test"); 但我不确定这是否是一个好的 MVVM 解决方案,我我不确定这是否意味着我最终会得到很多 DialogService 实例,因为每次我使用 ShowMessage 时它都会生成一个新的类实例。
  • 我只是想知道,如果我在我的每个 ViewModel 中使用这个声明:public virtual IDialogService DialogService =&gt; new DialogService();,然后像 DialogService.ShowMessage("Test"); 这样在整个 ViewModel 中使用服务的 ShowMessage 方法,那仍然是错误的?因为在我看来,这样 ViewModel 的依赖关系就很清楚了,而且在我看来,我可以使代码更加精简。抱歉,我还在学习中,非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-03
  • 2011-02-08
  • 2019-12-24
  • 2013-01-02
  • 1970-01-01
相关资源
最近更新 更多