Appendix#
Model–view–viewmodel (MVVM)#
Warning
MVVM adds unnecessary complexity for the goals of this course. The tutorial in Presenting data on a grid builds on the basic template we used in section Creating a GUI application.
Some reasons: MVVM requires an additional class (viewmodel) for each class of the model that should be shown on the GUI, which adds additional complexity. Moreover, the model classes should send a signal to the viewmodel whenever data in the model change, which can be hard to implement for beginners.
We introduce MVVM mainly because the the framework we utilize also uses MVVM.
- Model–view–viewmodel
an architectural pattern in computer software that facilitates the separation of the development of a GUI (the view) from the development of the business logic or back-end logic (the model).
Also referred as to:
MVVM in short.
model–view–binder
Fig. 24 Three components of MVVM. The return line from model to viewmodel is dashed because usually the viewmodel calls the model.
CC BY-SA 4.0. By Uncopy. Source: Wikimedia Commons#
- viewmodel
abstraction (e.g., OOP code) of the view. It uses the binder to synchronize GUI elements on the view with the model.
Remember that XAML defines both user interface elements and data-binding.
Creating an MVVM-based project#
New SolutionSelect
Avalonia .NET MVVM Appfrom the list with the name, e.g.,MVVMExample.After the project is opened you should see more directories compared to previous projects you created before, e.g.,
Models,ViewModels,Viewswhich correspond to the MVVM components we introduced before.Run the project.
It should show you the message
Welcome to Avalonia!.
Let us analyze how this message is presented to the user.
Open
MainWindow.axamland look at theTextBlock.You should see that
Textuses aBindingto the pathGreeting, which is an object in our code. But where?According to Fig. 24, data binding happens between the view and the viewmodel. The XAML describes the view, so
Greetingmust be in the viewmodel.Open
MainWindowViewModel.cs.You should see the property
Greetinginitialized with the welcome message.
Integrating a DataGrid into an MVVM-based template#
Make sure you have installed the
DataGridcontrol.Open
App.axamland append the<Styleincludeline after<FluentTheme>. After the modification theStyleincludeline should look as follows:<Application.Styles> <FluentTheme /> <StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml" /> </Application.Styles>
We need this, because
DataGriduses additional styles compared to the standard GUI elements.Under the directory
Models, create a new file calledModels.csthat will contain our model classes using right-click onModelsand thenAdd->File.In C# projects, usually we create a new file for each class, but to see all related classes at once, we will put them in a single file. It will be possible to separate them later.
You will be asked whether you want to add the file to Git.
Addit.Paste the following into
Models.cs:public class Person { public string FirstName { get; set; } public string LastName { get; set; } }
Notice the
getandsetkeywords for each field that we did not use before. These keywords introduce methods in the background that are used to get & setFirstNameandLastName. We need them; otherwise the GUI framework does not show any data. For example, if you remove{get; set;}fromLastName, then you will see noLastNamefield later when you run the program.We will call a field with
getorsetproperty.The reason for the behavior in the last paragraph could be that C# has a feature which allows to get the fields with get and set methods automatically, which in turn is used to show these data in DataGrid.
After the last step, you should see that
Personis gray underlined. Select the line withPersonand clickto choose context actions.
Click
Move to ... namespace.You will see that a namespace line is added.
Namespaces avoid naming clashes between models, viewmodels and views. Even the probability for naming clashes is very low in a small project, let us follow the structure of other classes in our MVVM template – also the classes in
ViewModelsandViewshave namespaces.Open
MainWindow.axaml.Replace the
TextBlockwith the following:<DataGrid Margin="20" ItemsSource="{Binding People}" AutoGenerateColumns="True" GridLinesVisibility="All" BorderThickness="1" BorderBrush="Gray"> </DataGrid>
These lines ensure the following:
Binding PeoplebindsPeopleto theDataGridso that the data on the GUI is updated automatically, when the data changes and vice-versa.AutoGenerateColumnsgenerates columns automatically by reading the properties of a class, e.g.,FirstNameandLastNameinPerson.Other four attributes including
Marginconfigure the style.
For more information about the attributes, refer to [
DataGriddocumentation][datagrid-docs].In the XAML, we see that the data is provided by the binding
People, which must be an object in the viewmodel.Open
MainWindowViewModel.cs.Add the following line on the top of the file:
using System.Collections.ObjectModel;
This library is required to make the
ObservableCollectionavailable.ObservableCollectionis a specialListthat can communicate with the GUI when data in the list is modified.Warning
Use
ObservableCollectioninstead ofListif you plan to present a list on the GUI.Delete the definition of the string
Greetingand replace it with the following:
public ObservableCollection<Person> People { get; }
public MainWindowViewModel()
{
var people = new List<Person>
{
new()
{
FirstName = "Melitta",
LastName = "Lipp"
},
new()
{
FirstName = "Heilos",
LastName = "König"
},
new()
{
FirstName = "Onur",
LastName = "KuĹźtepe"
}
};
People = new ObservableCollection<Person>(people);
}
This method creates an example dataset to show on the grid.
Run your project.
Try:
modifying data
changing sort order
This control is useful for editing data structured in the instances of a class.