MVVM List Detail pattern
code
ListDetail
https://github.com/mikihiro-t/MVVMPattern
Until now, I wrote List and Detail each time by trial and error, so I tried to summarize them in a pattern.
Development environment
Build with .NET Core 3.1 + ReactiveProperty.
ListViewModel and DetailViewModel
ListViewModel.cs
this.InfoList = this.Model.InfoList.ToReadOnlyReactiveCollection(x => new DetailViewModel(x)).AddTo(Disposable);
So, ** create each DetailViewModel
corresponding to each row of the DataGrid **.
When I first started learning MVVM, I didn’t know how to do this with DataGrid or ListView.
Show
The XAML for the Show button is:
Command calls the DataContext
of the DataGrid, that is, the ButtonShow
of the DataContext
(= ListViewModel
) of the Window.
The parameter becomes the DetailViewModel
on this line by CommandParameter = "{Binding}"
.
ListView.xaml
<Button Command="{Binding DataContext.ButtonShow, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" CommandParameter="{Binding}">Show</Button>
ListViewModel.cs
public ReactiveCommand<DetailViewModel> ButtonShow { get; } = new ReactiveCommand<DetailViewModel>();
** Receive the DetailViewModel
itself in that line as a parameter ** (where x is the parameter)
ListViewModel.cs
ButtonShow.Subscribe(x => ShowDetail(x)).AddTo(Disposable);
private void ShowDetail(DetailViewModel infoVM)
{
Model.ShowDetail(infoVM.Model);
}
Pass the Model (infoVM.Model)
held by the DetailViewModel
to the ListManager
to display the Detail
.
Therefore, the Model refers to the same thing in both the Row and Detail of the DataGrid, but the VMs are different.
If you want to display Detail using the same DetailViewModel used in the row of DataGrid,
ListViewModel.cs
private void ShowDetail(DetailViewModel infoVM)
At the stage of, you may use infoVM to display DetailView from ListViewModel.cs
. Then the row in the DataGrid and the DataContext
in the newly displayed DetailView will use the same DetailViewModel
.
Remove
It’s almost the same as Show.
new order
New in the order of Model → ViewModel → View.
Main.cs
var list = new ListManager();
ViewController.ShowListView(list);
I decided to handle the new of View and ViewModel in the public static
class of ViewController
.
ViewController.cs
public static void ShowListView(ListManager model)
{
var viewModel = new ListViewModel(model);
var view = new ListView(viewModel);
view.Show();
}
There is also a method of View → ViewModel → Model, but here Model comes first.
If the Model is running in the background and you want to display the View under certain conditions, you will have to put the Model first, and it is hard to think that there is no Model and only V and VM in MVVM, so Model first The idea is that it’s better to do new.
Dispose timing
What I don’t understand about ReactiveProperty
is when to call Dispose
.
DataGrid ViewModel
Clear / Remove of DataGrid is Clear
or Remove
of ʻObservableCollection
Detail ViewModel
When DetailView
is Close
, it is not known whether it will be Dispose
, so it is ** explicitly Dipose
**.
DetailViewModel.cs
private void Close()
{
CloseAction();
Dispose();
}
Impressions
The flow of processing is not clear, and unless you follow it while debugging, you can not understand it just by looking at the code. I think this is the difficult part of MVVM.
However, if you pattern it, it will be a little easier to get an idea of the processing flow.
MVVM article
- Pattern 1 View code behind
- Pattern 2 Command parameter
- Pattern 3 Prism Dialog Service