Reputation: 38209
I have PersonViewModel
, DepartmentViewModel
and their PersonView
, DepartmentView
.
PersonViewModel
has empty constructor, however DepartmentViewModel
has a parameter:
public class DepartmentViewModel
{
public DepartmentViewModel(ObservableCollection<Person> persons)
{}
}
I use the following service to open new window:
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();
}
}
the above service works really good. So far, it works okay till I wanted to send parameters to DepartmentViewModel
.
My App.xaml.cs
has all stuff to instantiate viewModels inside of OnStartup()
method:
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();
}
My question is how can I send a parameter to DepartmentViewModel
when I open new window from PersonViewModel
?
My code to open new window from 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);
}
How can I send ObservableCollection<Person> persons
to DepartmentViewModel
when I open new window through IDialogService
?
Upvotes: 0
Views: 652
Reputation: 3796
Perhaps you need a new Dialog/UIService then.
Here's a UiService I use to achieve the same effect as you. I don't use any IoC container. ViewLocator
is a simple class with a dictionary mapping from Vm type to View type. You could replace ViewLocator with whatever "ServiceLocator" you want ,though.
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;
}
}
All of my VMs have an IUiService property which is set when I call it's Init
method.
In the AppStartup, when I want to open my first window, I do :
Type windowType = ViewLocator.GetViewType<MainVm>()
var wnd = (Window)Activator.CreateInstance(windowType);
wnd.DataContext = new MainVm();
vm.Init(new UiService(wnd));
wnd.Show();
basically same as what I do in the UiService.Show
.
So when you want to Show
a ViewModel from another ViewModel, you call this.UiService.Show(new YourVm(parameters..));
.
IUiService.Show
will then determine the window type of your VM using the ViewLocator and create a new Window. It also assigns the IUiService for the new VM using that window.
IDialogReturnVm<T>
is an interface with a single property T ReturnInfo{get; private set;}
which you set inside your Vm.
This keeps the View and ViewModel decoupled pretty well, while still allowing you to pass parameters to ViewModel. I even have my ViewModels in a different assembly. The IUiService
is defined in that assembly and the implementation : UiService
is defined in the main assembly.
Upvotes: 1