We use MVVM mode extensively in the process of developing IQIYI UWP client. Here is a brief introduction of MVVM mode.
MVVM schema definition
MVVM includes three core modules: Model, View, View-Model
Model
-
Model is the actual data to be processed.
-
But it does not include operations or services that process these data.
-
Nor is it used to convert data into a format to facilitate UI display. Data conversion can be processed in ViewModel, or Converter can be defined to convert data.
-
Business logic is usually independent of Model and encapsulated into other classes to operate Model.
-
Models are easy to reuse and can be used in multiple ViewModel s.
-
Keeping the Model clean is challenging.
For example:
-
Business logic objects, such as User.
-
Data exchange object.
-
CLR meta-objects, int, long, string.
-
Automatically generated entities or proxy objects, such as entity classes corresponding to database tables, are used to parse entity classes for data such as JSON or XML.
View-Model
-
The middle layer of View and Model, commonly known as View's Model
-
Provide the ICommand attribute to View.
-
Provides other properties to manage the state of the View, such as whether Button is visible.
-
Call other services to get or manipulate the Model.
-
Aggregate one or more models and provide them to View through Property.
-
Implement INotifyPropertyChanged to meet the needs of UI binding updates.
-
For collections, use Observable Collection, etc.
View
- Contains topics, styles, UI layout, controls, data binding, events, and other interactions with users.
- Avoid excessive logical code, which should be put into ViewModel as much as possible
- View is usually defined in XAML, sometimes with a small amount of code.
- Get data from View Model by data binding or method call.
- Command attributes on UI controls can be bound to ICommand attributes of View Model.
- The state of UI controls can be controlled by binding properties to ViewModel.
The relationship between View and View-Model
- View and View Model are associated through data binding, method calls, attributes, events, etc.
- View Model exports Model to View and also needs to define other state information needed by View, such as IsAllowLogin.
- View needs to manage UI Events.
- Models and attributes in ViewModel are updated by bi-directional binding.
The relationship between ViewModel and Model
- View Model exports the Model, or binds it to View through attributes.
- View Model includes service interface, configuration data interface and so on, in order to obtain the data needed by View.
The Benefits of MVVM
- Development and design can work independently, and designers can debug the UI through simulated data.
- View Model and Model can unit test the code that is opposed to View.
- You can redesign the UI and reuse the code of View Model and Model.
- View Model, as an adapter between View and Model, can avoid changing View and need to modify Model.
Performance issues of MVVM
- Avoid excessive intermediate transition data, which can lead to excessive GC and thus affect performance.
- Data binding problem, data binding requires additional dynamic memory allocation, resulting in UI performance degradation. Use {x:Bind} instead of Binding to improve UI performance.
- Button.Click is usually bound to the Icommand attribute of View Model, which incurs additional overhead. It is recommended to use Click Event in the background code to call the View Model method in the event.
- Visibility attributes of parts that are not displayed to users are often bound to the attributes of View Model to control the visibility of this part of the UI. It is recommended to use x:Load or x: DeferLoad Strategy to delay the loading of this part of the UI.
Sample
Here's a simple example:
- Model
public class LoginModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string name) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name)); } private string userName = "Tester"; public string UserName { get { return userName; } set { userName = value; OnPropertyChanged(nameof(UserName)); } } private string password = string.Empty; public string Passowrd { get { return password; } set { password = value; OnPropertyChanged(nameof(Passowrd)); } } } - **ViewModel** - stay ViewModel Add LoginModel Examples. - stay ViewModel Add LoginCommand Attributes. ```java public class LoginViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private LoginModel loginModel = new LoginModel(); private ICommand loginCommand; public ICommand LoginCommand { get { return loginCommand; } } public LoginViewModel() { loginCommand = new LoginCommand(loginModel); } private void OnPropertyChanged(string name) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name)); } }
-
Command
- LoginModel is passed into LoginCommand, and LoginCommand is executable by judging UserName and Password of LoginModel.
public class LoginCommand : ICommand { public event EventHandler CanExecuteChanged; private LoginModel model; public LoginCommand(LoginModel model) { this.model = model; this.model.PropertyChanged += Model_PropertyChanged; } private void Model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == nameof(model.UserName) || e.PropertyName == nameof(model.Passowrd)) CanExecuteChanged?.Invoke(this, EventArgs.Empty); } public bool CanExecute(object parameter) { return !string.IsNullOrEmpty(this.model.UserName) && !string.IsNullOrEmpty(this.model.Passowrd); } public async void Execute(object parameter) { MessageDialog dlg = new MessageDialog($"Login with Name:{this.model.UserName} Password:{this.model.Passowrd}", "Login"); await dlg.ShowAsync(); } }
-
View.xaml
- Data Binding binds user name and password data to UserName and Password attributes of LoginModel.
- Button's Command is bound to LoginViewModel's LoginCommand property
<Page x:Class="ArchitectureTutorial.MVVM.LoginPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:ArchitectureTutorial.MVVM" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid Margin="24" HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <TextBlock Text="Sign in" Grid.ColumnSpan="2" HorizontalAlignment="Center" Margin="12" FontSize="18" /> <TextBlock Text="Sign in" Grid.ColumnSpan="2" HorizontalAlignment="Center" Margin="12" FontSize="18" /> <TextBlock Text="Password" Margin="6" HorizontalAlignment="Right" Grid.Row="2" /> <PasswordBox Grid.Row="2" Password="{x:Bind viewModel.LoginModel.Passowrd, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Margin="6" Grid.Column="1" Width="200" /> <Button x:Name="loginButton" Grid.Row="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Margin="12" Width="120" Height="32" Command="{x:Bind viewModel.LoginCommand}" CommandParameter="{x:Bind viewModel.LoginModel}" Content="Sign in" /> </Grid> </Page>
-
View.cs
- Define an instance of LoginViewModel.
public sealed partial class LoginPage : Page { private LoginViewModel viewModel = new LoginViewModel(); public LoginPage() { this.InitializeComponent(); } }
unit testing
- Create Add UnitTest Project
- Each time the code logic is modified, test cases can be run to check whether the logic is wrong.
public void TestLogin() { LoginViewModel viewModel = new LoginViewModel(); viewModel.LoginModel.UserName = "Test"; viewModel.LoginModel.Passowrd = "123"; Assert.IsTrue(viewModel.LoginCommand.CanExecute(null)); viewModel.LoginCommand.Execute(null); }
Reference
-
MVVM Best Practice
https://www.youtube.com/watch?v=ysWK4e2Mtco -
Model-View-ViewModel(MVVM) Explained
https://www.codeproject.com/articles/100175/model-view-viewmodel-mvvm-explained -
Fundamental MVVM
https://visualstudiomagazine.com/articles/2011/08/15/fundamental-mvvm.aspx -
MVVM Performance Tips
https://docs.microsoft.com/en-us/windows/uwp/debug-test-perf/mvvm-performance-tips
IQYI Win10 Professional Edition Client
- Simple interface operation, perfect support for touch screen devices, perfect fit for various screens
- No bullet window, no background process
- Supporting Dolby's sound effects, Dolby's horizons, and bringing about a better viewing experience