我遵循架构: 桌面应用程序,.Net 4.5,C#,WPF,MVVM Light,Messenger,IoC - ViewModel定位器,因此ViewModels不会对视图有所了解。
我有一些元素的数据网格主视图,我想在双击数据网格后显示新/子窗口中每个元素的详细信息。
我将主视图上的事件双击绑定到主视图模型。从主视图模型中的此事件处理程序,消息通过Messanger发送。
在主视图中通过双击代表创建新视图(新/子窗口)。
新建/子窗口是一个视图,它将视图模型和此视图模型注册到其构造函数中的特定消息。
问题是新的/子窗口(新视图和视图模型等)创建得太晚了,因为当新视图模型为它注册时已经发送了消息。
你知道这种架构的某些模式吗?任何想法将不胜感激。
答案 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>();
}
}
}