MVVM指示灯,通过Messenger从ViewModel发送消息到新的子窗口,该子窗口尚未初始化

时间:2014-01-22 23:23:49

标签: c# wpf mvvm desktop-application

我遵循架构: 桌面应用程序,.Net 4.5,C#,WPF,MVVM Light,Messenger,IoC - ViewModel定位器,因此ViewModels不会对视图有所了解。

我有一些元素的数据网格主视图,我想在双击数据网格后显示新/子窗口中每个元素的详细信息。

我将主视图上的事件双击绑定到主视图模型。从主视图模型中的此事件处理程序,消息通过Messanger发送。

在主视图中通过双击代表创建新视图(新/子窗口)。

新建/子窗口是一个视图,它将视图模型和此视图模型注册到其构造函数中的特定消息。

问题是新的/子窗口(新视图和视图模型等)创建得太晚了,因为当新视图模型为它注册时已经发送了消息。

你知道这种架构的某些模式吗?任何想法将不胜感激。

2 个答案:

答案 0 :(得分:0)

确切地知道你要做什么会有所帮助。

如果您的问题只是在双击行时显示详细的窗口,我会说:在开始时只创建一个childWindow,并在需要时播放其可见性。

如果您每次都需要一个新窗口,可以使用注入服务从viewModel创建它。

无论如何,您永远不必从主视图创建窗口!您可以在开始时创建一个窗口,也可以从视图模型中动态创建它。

您无法希望从视图中创建它并在视图模型中发送消息。

编辑注入的服务,你可以使用类似的东西:

   public interface IWindowService
   {
    void Open<TWindow>(ViewModelBase viewModel)
        where TWindow : Window;
   }

    public class WindowService : IWindowService
    {
        private readonly IUIDispatcher _dispatcher;

        public WindowService(IUIDispatcher dispatcher)
        {
            _dispatcher = dispatcher;
        }

        public void Open<TWindow>(ViewModelBase viewModel)
            where TWindow : Window
        {
            _dispatcher.Run(() => OpenThreadSafe<TWindow>(viewModel));
        }

        private static void OpenThreadSafe<TWindow>(ViewModelBase viewModel) where TWindow : Window
        {
            var view = (TWindow) Activator.CreateInstance(typeof(TWindow), viewModel);
            view.Show();
        }
    }

public class UIDispatcher : IUIDispatcher
{
    public void Run(Action action)
    {
        var dispatcher = DispatcherHelper.UIDispatcher;
        if (dispatcher == null)
        {
            action();
            return;
        }

        DispatcherHelper.CheckBeginInvokeOnUI(action);
    }

请注意,此DispatcherHelper来自MVVMlight,但您可以轻松地将其置换。

希望它有所帮助。

答案 1 :(得分:0)

问题是ViewModel Locator仅在需要时才创建viewmodel实例(延迟加载)。

只需将ViewModelLocator配置为实例化viewmodel eager而不是lazy。这是通过将参数“true”传递给IoC容器来完成的。

样品:

namespace Administration.ViewModel
{
    public class ViewModelLocator
    {
        public ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            //Eager Loading
            SimpleIoc.Default.Register<UserManagementViewModel>(true);

            //Lazy Loading
            SimpleIoc.Default.Register<InformationManagementViewModel>();
        }

        public UserManagementViewModel UserManagementViewModel
        {
            get
            {
                return ServiceLocator.Current.GetInstance<UserManagementViewModel>();
            }
        }

        public InformationManagementViewModel InformationManagementViewModel
        {
            get
            {
                return ServiceLocator.Current.GetInstance<InformationManagementViewModel>();
            }
        }

        public static void Cleanup()
        {
            SimpleIoc.Default.Unregister<UserManagementViewModel>();
            SimpleIoc.Default.Unregister<InformationManagementViewModel>();
        }
    }
}