C# 使用MVVM从WPF应用程序启动对话框/子窗口的标准方法

C# 使用MVVM从WPF应用程序启动对话框/子窗口的标准方法,c#,wpf,mvvm,dialog,C#,Wpf,Mvvm,Dialog,总之,我想知道使用MVVM模式从WPF启动[child]对话框/窗口的公认最佳方法/行业标准。我看到了以下文章: A 这种方法看起来不错,但对我来说太过分了。这是某种程度的代码复制,我不相信这是正确的方法 B 本文简要介绍了三个选项,其中包含各种链接,这些链接在解释方法或主题方面都相当/非常差 请有人解释一下使用MVVM从WPF应用程序启动对话框的行业标准方法/方法,最好是提供一些指向进一步阅读材料的链接?如果你能自己举个例子,我当然非常感激 谢谢您的时间。创建对话服务对我来说效果很好,在您的两

总之,我想知道使用MVVM模式从WPF启动[child]对话框/窗口的公认最佳方法/行业标准。我看到了以下文章:

A

这种方法看起来不错,但对我来说太过分了。这是某种程度的代码复制,我不相信这是正确的方法

B

本文简要介绍了三个选项,其中包含各种链接,这些链接在解释方法或主题方面都相当/非常差

请有人解释一下使用MVVM从WPF应用程序启动对话框的行业标准方法/方法,最好是提供一些指向进一步阅读材料的链接?如果你能自己举个例子,我当然非常感激


谢谢您的时间。

创建对话服务对我来说效果很好,在您的两个链接中都有建议

后来,我在年的开发日上看到了相同的解决方案。检查工作代码示例的链接(尽管是为Metro编写的)

关于dialog服务,唯一让我感到不安的是它在某种程度上依赖于UI技术(富客户端)


一个简单的请求-响应web前端视图可以构建在WPF XAML绑定到的相同ViewModel和模型代码之上。直到ViewModel开始通过对话框服务弹出对话框。我不知道如何为web视图实现对话服务。在视图中实现对话框需要更多的逻辑。

使用接口实现对话框的目的是使代码可测试。在这种情况下,“A”被广泛使用,但仍然很难说“标准”。如果您没有对ViewModel进行测试,或者您可以测试ViewModel以避免触摸对话框,例如使用提取覆盖,那么您绝对不能按照说明操作。

首先,我不知道使用MVVM显示对话框的任何“行业标准”方法,因为没有这种方法。
其次,欢迎来到MVVM,您刚刚谈到了MVVM没有标准的领域。
说实话,MVVM有很多痛点,这就是为什么有很多MVVM框架存在的原因,仅举几个MVVM Light、PRISM、Caliburn。Micro、Cinch、Catel、WAF、Baboon、shell我停下来,或者你想要更多。
现在,为了回答您的问题,在处理了大多数这些框架之后,我注意到了一个共同点,它们都使用DI/IoC容器,然后为您提供一个接口,类似于IDialogManager和它们自己的实现,然后它们要求您在视图模型中接受这个接口,并使用它来显示对话框。总之,我将使用依赖注入,有一个显示对话框的界面,然后提供和实现该界面,并将其注册到di容器中,然后从我的视图模型或视图中使用它。

编辑:所以你选择了PRISM(在我看来),在显示对话框时,PRISM是它们中最难的一个。现在抛开这一点不谈,还有一个困难的方法是使用(查看本文中间部分),或者您可以使用它作为一种更快的方法。

最近,我为WPF实现了自己的导航服务,它使用Caliburn.Micro的WindowManager(但您可以用其他东西代替它)

示例(如何使用):

_navigationService.GetWindow<ClientDetailsViewModel>()
            .WithParam(vm => vm.IsEditing, true)
            .WithParam(vm => vm.Client, SelectedClient)
            .DoIfSuccess(() => RefreshSelectedClient())
            .ShowWindowModal();
namespace ClientApplication.Utilities
{
    public class NavigationService : INavigationService
    {
        SimpleContainer _container;
        IWindowManager _windowManager;

        public NavigationService(SimpleContainer container, IWindowManager windowManager)
        {
            _container = container;
            _windowManager = windowManager;
        }

        public INavigationService<TViewModel> GetWindow<TViewModel>()
        {
            return new NavigationService<TViewModel>(_windowManager, (TViewModel)_container.GetInstance(typeof(TViewModel), null));
        }
    }




    public class NavigationService<TVM> : INavigationService<TVM>
    {
        IWindowManager _windowManager;
        TVM _viewModel;
        System.Action _action;

        public NavigationService(IWindowManager windowManager, TVM viewModel)
        {
            _windowManager = windowManager;
            _viewModel = viewModel;
        }

        public INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value)
        {
            var prop = (PropertyInfo)((MemberExpression)property.Body).Member;
            prop.SetValue(_viewModel, value, null);

            return this;
        }

        public INavigationService<TVM> DoBeforeShow(Action<TVM> action)
        {
            action(_viewModel);
            return this;
        }

        public INavigationService<TVM> DoIfSuccess(System.Action action)
        {
            _action = action;
            return this;
        }

        public void ShowWindow(IDictionary<string, object> settings = null)
        {
            _windowManager.ShowWindow(_viewModel, null, settings);
        }

        public bool ShowWindowModal(IDictionary<string, object> settings = null)
        {
            bool result = _windowManager.ShowDialog(_viewModel, null, settings) ?? false;
            if (result && _action != null)
                _action();

            return result;
        }
    }
}
namespace Common
{
    public interface INavigationService<TVM>
    {
        INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value);

        INavigationService<TVM> DoIfSuccess(System.Action action);

        INavigationService<TVM> DoBeforeShow(Action<TVM> action);

        void ShowWindow(IDictionary<string, object> settings = null);

        bool ShowWindowModal(IDictionary<string, object> settings = null);
    }



    public interface INavigationService
    {
        INavigationService<TViewModel> GetWindow<TViewModel>();
    }
}
\u navigationService.GetWindow()
.WithParam(vm=>vm.IsEditing,true)
.WithParam(vm=>vm.Client,SelectedClient)
.DoIfSuccess(()=>RefreshSelectedClient())
.ShowWindowModal();
实施:

_navigationService.GetWindow<ClientDetailsViewModel>()
            .WithParam(vm => vm.IsEditing, true)
            .WithParam(vm => vm.Client, SelectedClient)
            .DoIfSuccess(() => RefreshSelectedClient())
            .ShowWindowModal();
namespace ClientApplication.Utilities
{
    public class NavigationService : INavigationService
    {
        SimpleContainer _container;
        IWindowManager _windowManager;

        public NavigationService(SimpleContainer container, IWindowManager windowManager)
        {
            _container = container;
            _windowManager = windowManager;
        }

        public INavigationService<TViewModel> GetWindow<TViewModel>()
        {
            return new NavigationService<TViewModel>(_windowManager, (TViewModel)_container.GetInstance(typeof(TViewModel), null));
        }
    }




    public class NavigationService<TVM> : INavigationService<TVM>
    {
        IWindowManager _windowManager;
        TVM _viewModel;
        System.Action _action;

        public NavigationService(IWindowManager windowManager, TVM viewModel)
        {
            _windowManager = windowManager;
            _viewModel = viewModel;
        }

        public INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value)
        {
            var prop = (PropertyInfo)((MemberExpression)property.Body).Member;
            prop.SetValue(_viewModel, value, null);

            return this;
        }

        public INavigationService<TVM> DoBeforeShow(Action<TVM> action)
        {
            action(_viewModel);
            return this;
        }

        public INavigationService<TVM> DoIfSuccess(System.Action action)
        {
            _action = action;
            return this;
        }

        public void ShowWindow(IDictionary<string, object> settings = null)
        {
            _windowManager.ShowWindow(_viewModel, null, settings);
        }

        public bool ShowWindowModal(IDictionary<string, object> settings = null)
        {
            bool result = _windowManager.ShowDialog(_viewModel, null, settings) ?? false;
            if (result && _action != null)
                _action();

            return result;
        }
    }
}
namespace Common
{
    public interface INavigationService<TVM>
    {
        INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value);

        INavigationService<TVM> DoIfSuccess(System.Action action);

        INavigationService<TVM> DoBeforeShow(Action<TVM> action);

        void ShowWindow(IDictionary<string, object> settings = null);

        bool ShowWindowModal(IDictionary<string, object> settings = null);
    }



    public interface INavigationService
    {
        INavigationService<TViewModel> GetWindow<TViewModel>();
    }
}
namespace ClientApplication.Utilities
{
公共类导航服务:INavigationService
{
SimpleContainer\u容器;
iWindows管理器\u windowManager;
公共导航服务(SimpleContainer容器、iWindows管理器windowManager)
{
_容器=容器;
_windowManager=windowManager;
}
公共INavigationService GetWindow()
{
返回新的导航服务(_windowManager,(TViewModel)_container.GetInstance(typeof(TViewModel),null));
}
}
公共类导航服务:INavigationService
{
iWindows管理器\u windowManager;
TVM_视图模型;
系统动作(Action);;
公共导航服务(iWindows管理器windowManager、TVM viewModel)
{
_windowManager=windowManager;
_viewModel=viewModel;
}
带参数的公共INavigationService(表达式属性,TProperty值)
{
var prop=(PropertyInfo)((MemberExpression)property.Body.Member;
prop.SetValue(_viewModel,value,null);
归还这个;
}
公共INavigationService DoBeforeShow(行动)
{
动作(_viewModel);
归还这个;
}
public INavigationService DoIfSuccess(System.Action动作)
{
_行动=行动;
归还这个;
}
公共无效显示窗口(IDictionary设置=null)
{
_windowManager.ShowWindow(_viewModel,null,settings);
}
public bool ShowWindowModal(IDictionary设置=null)
{
bool result=\u windowManager.ShowDialog(\u viewModel,null,settings)??false;
if(结果和操作!=null)
_动作();
返回结果;
}
}
}
接口:

_navigationService.GetWindow<ClientDetailsViewModel>()
            .WithParam(vm => vm.IsEditing, true)
            .WithParam(vm => vm.Client, SelectedClient)
            .DoIfSuccess(() => RefreshSelectedClient())
            .ShowWindowModal();
namespace ClientApplication.Utilities
{
    public class NavigationService : INavigationService
    {
        SimpleContainer _container;
        IWindowManager _windowManager;

        public NavigationService(SimpleContainer container, IWindowManager windowManager)
        {
            _container = container;
            _windowManager = windowManager;
        }

        public INavigationService<TViewModel> GetWindow<TViewModel>()
        {
            return new NavigationService<TViewModel>(_windowManager, (TViewModel)_container.GetInstance(typeof(TViewModel), null));
        }
    }




    public class NavigationService<TVM> : INavigationService<TVM>
    {
        IWindowManager _windowManager;
        TVM _viewModel;
        System.Action _action;

        public NavigationService(IWindowManager windowManager, TVM viewModel)
        {
            _windowManager = windowManager;
            _viewModel = viewModel;
        }

        public INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value)
        {
            var prop = (PropertyInfo)((MemberExpression)property.Body).Member;
            prop.SetValue(_viewModel, value, null);

            return this;
        }

        public INavigationService<TVM> DoBeforeShow(Action<TVM> action)
        {
            action(_viewModel);
            return this;
        }

        public INavigationService<TVM> DoIfSuccess(System.Action action)
        {
            _action = action;
            return this;
        }

        public void ShowWindow(IDictionary<string, object> settings = null)
        {
            _windowManager.ShowWindow(_viewModel, null, settings);
        }

        public bool ShowWindowModal(IDictionary<string, object> settings = null)
        {
            bool result = _windowManager.ShowDialog(_viewModel, null, settings) ?? false;
            if (result && _action != null)
                _action();

            return result;
        }
    }
}
namespace Common
{
    public interface INavigationService<TVM>
    {
        INavigationService<TVM> WithParam<TProperty>(Expression<Func<TVM, TProperty>> property, TProperty value);

        INavigationService<TVM> DoIfSuccess(System.Action action);

        INavigationService<TVM> DoBeforeShow(Action<TVM> action);

        void ShowWindow(IDictionary<string, object> settings = null);

        bool ShowWindowModal(IDictionary<string, object> settings = null);
    }



    public interface INavigationService
    {
        INavigationService<TViewModel> GetWindow<TViewModel>();
    }
}
名称空间公用
{
公共接口INavigationService
{
INavigationService WithParam(表达式属性,TProperty值);
INavigationService DoIfSuccess(系统动作动作);
INavigationService-DoBeforeShow(动作动作);
void ShowWindow(IDictionary设置=null);
bool ShowWindowModal(IDictionary设置=