我有PersonViewModel
,DepartmentViewModel
和他们的PersonView
,DepartmentView
。
PersonViewModel
有空构造函数,但DepartmentViewModel
有一个参数:
public class DepartmentViewModel
{
public DepartmentViewModel(ObservableCollection<Person> persons)
{}
}
我使用以下服务打开新窗口:
public interface IDialogService<T>
{
void Show(IUnityContainer unityContainer);
void ShowDialog(IUnityContainer unityContainer);
}
public class DialogService<T> : IDialogService<T> where T : Window
{
public void Show(IUnityContainer unityContainer)
{
var container = unityContainer;
container.Resolve<T>().Show();
}
public void ShowDialog(IUnityContainer unityContainer)
{
var container = unityContainer;
container.Resolve<T>().ShowDialog();
}
}
以上服务工作真的很好。到目前为止,它可以正常工作,直到我想将参数发送到DepartmentViewModel
。
我的App.xaml.cs
包含了在OnStartup()
方法中实例化viewModels的所有内容:
protected override void OnStartup(StartupEventArgs e)
{
_container = new UnityContainer();
_container.RegisterType<IViewMainWindowViewModel, MainWindow>();
_container.RegisterType<IViewMainWindowViewModel, MainViewModel>();
_container.RegisterType<IViewPersonViewModel, PersonView>();
_container.RegisterType<IViewPersonViewModel, PersonViewModel>(new ContainerControlledLifetimeManager());
_container.RegisterType<IViewDepartmentViewModel, DepartmentView>();
_container.RegisterType<IViewDepartmentViewModel, DepartmentViewModel>(new ContainerControlledLifetimeManager());
//types
_container.RegisterType(typeof(IDialogService<>), typeof(DialogService<>));
_container.Resolve<MainWindow>().Show();
}
我的问题是,当我从DepartmentViewModel
打开新窗口时,如何向PersonViewModel
发送参数?
我的代码是从PersonViewModel
打开新窗口:
private readonly IDialogService<DepartmentView> _dialogDepartmentView;
public void ContinueCommand_DoWork(object obj)
{
//want to send "persons" to departmentViewModel
ObservableCollection<Person> persons = new ObservableCollection<Person>();
// Open new dialog
_dialogDepartmentView.ShowDialog(_unityContainer);
}
当我通过ObservableCollection<Person> persons
打开新窗口时,如何将DepartmentViewModel
发送到IDialogService
?
答案 0 :(得分:1)
也许你需要一个新的Dialog / UIService。
这是我用来实现与你相同效果的UiService。我不使用任何IoC容器。 ViewLocator
是一个简单的类,其中包含从Vm类型到View类型的字典映射。您可以将ViewLocator替换为您想要的任何“ServiceLocator”。
public interface IUiService {
void Close();
void Show<TVm>(TVm vm) where TVm : ViewModel;
public T ShowDialog<T, TVm>(TVm vm)
where T : class
where TVm : ViewModel, IDialogReturnVm<T>;
}
public class UiService : IUiService
{
private readonly Window window;
public UiService(Window window)
{
this.window = window;
}
public void Close()
{
this.window.Close();
}
public void Show<TVm>(TVm vm) where TVm : ViewModel
{
Type windowType = ViewLocator.GetViewType<TVm>()
var wnd = (Window)Activator.CreateInstance(windowType);
wnd.DataContext = vm;
wnd.Owner = Application.Current.MainWindow;
vm.Init(new UiService(wnd));
wnd.Show();
}
public T ShowDialog<T, TVm>(TVm vm)
where T : class //T is the type of imformation which the Vm will "return" when it's window is closed.
where TVm : ViewModel, IDialogReturnVm<T>
{
Type windowType = ViewLocator.GetViewType<TVm>()
var wnd = (Window)Activator.CreateInstance(windowType);
wnd.DataContext = vm;
wnd.Owner = Application.Current.MainWindow;
vm.Init(new UiService(wnd));
wnd.ShowDialog();
return vm.ReturnInfo;
}
}
我的所有虚拟机都有一个IUiService属性,当我调用它的Init
方法时会设置该属性。
在AppStartup中,当我想打开第一个窗口时,我会这样做:
Type windowType = ViewLocator.GetViewType<MainVm>()
var wnd = (Window)Activator.CreateInstance(windowType);
wnd.DataContext = new MainVm();
vm.Init(new UiService(wnd));
wnd.Show();
与我在UiService.Show
中所做的基本相同。
因此,当您想要Show
来自其他ViewModel的ViewModel时,请调用this.UiService.Show(new YourVm(parameters..));
。
IUiService.Show
将使用ViewLocator确定VM的窗口类型并创建一个新窗口。它还使用该窗口为新VM分配IUiService。
IDialogReturnVm<T>
是一个包含您在Vm中设置的单个属性T ReturnInfo{get; private set;}
的接口。
这使View和ViewModel保持良好分离,同时仍允许您将参数传递给ViewModel。我甚至将ViewModel放在不同的程序集中。 IUiService
在该程序集中定义,并且实现:UiService
在主程序集中定义。