MVVM support in UWP.MDI
UWP.MDI is a library for building MDI applications in UWP. In the introduction post I mentioned that UWP.MDI has two goals:
- To provide comprehensive MDI support for UWP applications.
- To provide MDI support in such a way that those familiar with Windows Forms' MDI support feel at home.
One goal was missing from that list: Making UWP the best platform for building MDI applications. That means that when using UWP.MDI, we should be able to reap the benefits which UWP has over Windows Forms: XAML, data binding and the MVVM paradigm.
MVVM and UWP.MDI
To see how UWP.MDI and MVVM play together, there’s now a new sample in the repo: https://github.com/mikoskinen/UWP.MDI/tree/master/samples/UWP.MDI.MVVM
The sample doesn’t use any MVVM framework to make it clean. It contains a ViewModelLocator which is used to hook forms and view models together but other than that, it’s straight forward.
The sample contains the Main page (MDI Container) and two forms (Customers, Invoices). Each of these has a corresponding view model. For example here’s the CustomerViewModel which is bind against the form:
public CustomerViewModel() { var customers = new ObservableCollection<Customer>(); var names = new List<Tuple<string, string>> { Tuple.Create("Noel", "Hess"), Tuple.Create("Silver", "Holland"), Tuple.Create("Rudy", "Phillips"), Tuple.Create("Skylar", "Cabrera"), Tuple.Create("Blair", "Kirby"), }; for (int i = 0; i < names.Count; i++) { var id = i + 1; var name = names[i]; var customer = new Customer(id, name.Item1, name.Item2); customers.Add(customer); } Customers = customers; } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
The form itself hooks up with the view model through the ViewModelLocator:
<UserControl x:Class="UWP.MDI.Samples.MVVM.Customers.CustomerForm" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:grid="using:Telerik.UI.Xaml.Controls.Grid" xmlns:controls="using:UWP.MDI.Controls" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400" Width="450" Height="400" controls:FormProperties.Text="Customers" DataContext="{Binding CustomerViewModel, Source={StaticResource ViewModelLocator}}"> <Grid> <Grid> <grid:RadDataGrid x:Name="DataGrid" ItemsSource="{Binding Customers}"/> </Grid> </Grid> </UserControl>
We use commands to display the forms through the MainPageViewModel:
public class MainPageViewModel { public ICommand ShowCustomersCommand { get; set; } public ICommand ShowInvoicesCommand { get; set; } public ICommand ExitCommand { get; set; } public MainPageViewModel() { ShowCustomersCommand = new RelayCommand(() => { var frm = new Customers.CustomerForm(); frm.Show(); }); ShowInvoicesCommand = new RelayCommand(() => { var frm = new Invoices.InvoiceForm(); frm.Show(); }); ExitCommand = new RelayCommand(() => { Application.Current.Exit(); }); } }
All in all, straight forward code if you’re familiar with MVVM.
Coming soon
A sample which uses Caliburn.Micro is coming soon. Caliburn.Micro is a full blown MVVM framework and creating a sample for it is a good way to make sure that UWP.MDI has the required extensions points to make it work correctly with all the MVVM frameworks out there.