Cutting edge MVVMLight 2: Description of Model, View, ViewModel structure, and global View Model injector, mvvmlightviewmodel
In the previous article, we have introduced how to use NuGet to apply MVVMLight to our WPF project. This article describes the structure and running mode required by the next basic MVVMLight framework. After MVVMLight is installed, we can see a simple framework layout, such as the previous article, which generates a ViewModel folder. The content of the ViewModel layer is put here, except for the ViewModel of the Main object, it also contains a ViewModelLocator file used to inject the current global ViewModel instance.I. Let's talk about the layered structure first:1. View is responsible for front-end display and interaction of data and commands with ViewModel. 2. ViewModel is responsible for organizing the business-level logical structure of the front-end view and giving feedback to the front-end. 3. Model: mainly responsible for data entity structure processing and interaction with ViewModel. Based on the above layer, we encode the code. First, create a directory with a complete three-tier structure, including the three-tier folder "Model", "View", and "ViewModel:1. Write a Model with the following code:
1 using GalaSoft. mvvmLight; 2 using System; 3 using System. collections. generic; 4 using System. linq; 5 using System. text; 6 using System. threading. tasks; 7 8 namespace MVVMLightDemo. model 9 {10 public class WelcomeModel: ObservableObject11 {12 private String introduction; 13 /// <summary> 14 // welcome word 15 /// </summary> 16 public String Introduction17 {18 get {return introduction;} 19 set {introduction = value; raisePropertyChanged () => Introduction);} 20} 21} 22}
It is very simple. It only contains an object. Here, we note that it inherits a parent class: ObservableObject. The role of this parent class is to ensure that the attribute is changed. It implements the INotifyPropertyChanged interface and notifies the UI of changes by triggering the PropertyChanged event. Therefore, when defining an object, we only need to call RaisePropertyChanged (PropertyName) you can make a notification of attribute changes. Therefore, when RaisePropertyChanged (PropertyName) is added to each attribute defined in the object, the UI interaction can be updated.
2. Write a VideModel to interact with the View.
1 using GalaSoft. mvvmLight; 2 using MVVMLightDemo. model; 3 using System; 4 using System. collections. generic; 5 using System. linq; 6 using System. text; 7 using System. threading. tasks; 8 9 namespace MVVMLightDemo. viewModel10 {11 public class WelcomeViewModel: ViewModelBase12 {13 /// <summary> 14 /// constructor 15 /// </summary> 16 public WelcomeViewModel () 17 {18 Welcome = new WelcomeModel () {Introduction = "H Ello World! "}; 19} 20 # region attribute 21 22 private WelcomeModel welcome; 23 /// <summary> 24 /// welcome word attribute 25 /// </summary> 26 public WelcomeModel 27 {28 get {return welcome;} 29 set {welcome = value; raisePropertyChanged () => Welcome);} 30} 31 # endregion32} 33}
It is also very simple. It contains a WelcomeModel attribute named Welcome that inherits the parent class of ViewBaseModel. ViewBaseModel inherits both the ObservableObject class and the ICleanup interface. Therefore, the INotifyPropertyChanged interface can be used to trigger the PropertyChanged event to notify the View. The Welcome attribute is instantiated in the constructor.
3. Write a View to display and interact with the ViewModel.
1 <Window x:Class="MVVMLightDemo.View.WelcomeView" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="WelcomeView" Height="300" Width="300"> 5 <Grid> 6 <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" > 7 <TextBlock Text="{Binding Welcome.Introduction}" FontSize="30" ></TextBlock> 8 </StackPanel> 9 </Grid>10 </Window>
TextBlock is bound to Welcome. Introduction, so the Introduction attribute under the Welcome object should be displayed.
At this time, ViewModel and View are irrelevant, So we write the following code in the code-Behind constructor:
1 using MVVMLightDemo.ViewModel; 2 using System.Windows; 3 4 namespace MVVMLightDemo.View 5 { 6 /// <summary> 7 /// Interaction logic for WelcomeView.xaml 8 /// </summary> 9 public partial class WelcomeView : Window10 {11 public WelcomeView()12 {13 InitializeComponent();14 this.DataContext = new WelcomeViewModel();15 }16 }17 }
Assign the WelcomeViewModel value to the data context of the current view. Therefore, all public attributes and commands of ViewModel can be used in the current view.
The execution result is as follows:
Ii. Let's talk about the constructor:If NuGet is used to install the complete MVVM Light framework, instead of MVVM Light libraries only, ViewModelLocator class is always included, and the resource dictionary is generated and added to global resources.
1 <Application x:Class="MVVMLightDemo.App" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 StartupUri="View/WelcomeView.xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 d1p1:Ignorable="d" 7 xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 xmlns:vm="clr-namespace:MVVMLightDemo.ViewModel" > 9 <Application.Resources>10 <ResourceDictionary>11 <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />12 </ResourceDictionary>13 </Application.Resources>14 </Application>
Therefore, the ViewModelLocator class is initialized every time the App is initialized.
In fact, it is a basic view model injector. Register the used ViewModel In the constructor and generate a single instance. Then, we use the attribute to expose it. Whenever we access the attribute, the corresponding ViewModel instance will be returned.
1/* 2 In App. xaml: 3 <Application. resources> 4 <vm: ViewModelLocator xmlns: vm = "clr-namespace: MVVMLightDemo" 5 x: Key = "Locator"/> 6 </Application. resources> 7 8 In the View: 9 DataContext = "{Binding Source = {StaticResource Locator }, path = ViewModelName} "10 11 You can also use Blend to do all this with the tool's support.12 See http://www.galasoft.ch/mvvm13 */14 15 using GalaSoft. mvvmLight; 16 using GalaSoft. mvvmLight. ioc; 17 using Microsoft. practices. serviceLocation; 18 19 namespace MVVMLightDemo. viewModel20 {21 // <summary> 22 // This class contains static references to all the view models in the23 // application and provides an entry point for the bindings.24 /// </summary> 25 public class ViewModelLocator26 {27 // <summary> 28 // Initializes a new instance of the ViewModelLocator class.29 // </summary> 30 public ViewModelLocator () 31 {32 ServiceLocator. setLocatorProvider () => SimpleIoc. default); 33 34 # region Code Example35 // if (ViewModelBase. isInDesignModeStatic) 36 // {37 /// Create design time view services and models38 /// SimpleIoc. default. register <IDataService, DesignDataService> (); 39 //} 40 // else41 // {42 // Create run time view services and models43 // SimpleIoc. default. register <IDataService, DataService> (); 44 //} 45 # endregion46 47 SimpleIoc. default. register <MainViewModel> (); 48} 49 50 # region instantiation 51 public MainViewModel Main52 {53 get54 {55 return ServiceLocator. current. getInstance <MainViewModel> (); 56} 57} 58 59 # endregion60 61 public static void Cleanup () 62 {63 // TODO Clear the ViewModels64} 65} 66}
Note that the SimpleIoc provided by MVVMLight is used as the default service provider. It is a simple injection framework. In order to unify and see the ViewModel data during design, ServiceLocator wrapped SimpleIoc in a layer. We wrote a Hello World File above, which can be modified in this way.
1/* 2 In App. xaml: 3 <Application. resources> 4 <vm: ViewModelLocator xmlns: vm = "clr-namespace: MVVMLightDemo" 5 x: Key = "Locator"/> 6 </Application. resources> 7 8 In the View: 9 DataContext = "{Binding Source = {StaticResource Locator }, path = ViewModelName} "10 11 You can also use Blend to do all this with the tool's support.12 See http://www.galasoft.ch/mvvm13 */14 15 using GalaSoft. mvvmLight; 16 using GalaSoft. mvvmLight. ioc; 17 using Microsoft. practices. serviceLocation; 18 19 namespace MVVMLightDemo. viewModel20 {21 // <summary> 22 // This class contains static references to all the view models in the23 // application and provides an entry point for the bindings.24 /// </summary> 25 public class ViewModelLocator26 {27 // <summary> 28 // Initializes a new instance of the ViewModelLocator class.29 // </summary> 30 public ViewModelLocator () 31 {32 ServiceLocator. setLocatorProvider () => SimpleIoc. default); 33 34 # region Code Example35 // if (ViewModelBase. isInDesignModeStatic) 36 // {37 /// Create design time view services and models38 /// SimpleIoc. default. register <IDataService, DesignDataService> (); 39 //} 40 // else41 // {42 // Create run time view services and models43 // SimpleIoc. default. register <IDataService, DataService> (); 44 //} 45 # endregion46 47 SimpleIoc. default. register <MainViewModel> (); 48 SimpleIoc. default. register <WelcomeViewModel> (); 49} 50 51 # region instantiate 52 public MainViewModel Main53 {54 get55 {56 return ServiceLocator. current. getInstance <MainViewModel> (); 57} 58} 59 60 public WelcomeViewModel Welcome61 {62 get63 {64 return ServiceLocator. current. getInstance <WelcomeViewModel> (); 65} 66} 67 68 # endregion69 70 public static void Cleanup () 71 {72 // TODO Clear the ViewModels73} 74} 75}
After registering the WelcomeViewModel instance, we can use it in the corresponding View. The original
1 public WelcomeView()2 {3 InitializeComponent();4 this.DataContext = new WelcomeViewModel();5 }
This. DataContext = new WelcomeViewModel (); can be removed and written directly in WelcomeView as follows:
DataContext = "{Binding Source = {StaticResource Locator}, Path = Welcome}", for example, the advantage of doing so is that the Binding method is more reasonable than the simple and crude Assignment Method. One is to see the bound data in the visualization window, achieving what you see is what you get. As follows: After compiling the bound data, it will be immediately displayed: the server-side developers can concentrate on the business logic code of ViewModel, And the UI developers can focus on the design view, similarly, ViewModel can be bound to different views. Therefore, three important features of ViewModel are shown here: low coupling, reusability, and independent development. Have you found a ClearnUp () method in the ViewModelLocator class to clear ViewModel instances. ViewModelBase inherits the GalaSoft. MvvmLight. ICleanup interface and writes the Cleanup () virtual method in its own class. Therefore, we can override Cleanup () in the ViewModel class of the instance to clear the current instance. This will be detailed in the subsequent articles about Data Binding and commands. Click the sample code in the Download text to repost it. indicate the source. Thank you.