MVVM journey (1) Create the simplest MVVM program and mvvm journey

Source: Internet
Author: User

MVVM journey (1) Create the simplest MVVM program and mvvm journey

This is the first article in The MVVM journey series. Many articles and books like to introduce the background and significance of a technology at the beginning, but I think for programmers, a program that can run directly may be more intuitive for them to understand this technology. In this article, I will take you step by step to create the simplest MVVM program. Although the program is simple, it covers the basic elements of MVVM, for those who are not familiar with MVVM, I believe this will be a good start.

The function of the program is very simple: two buttons, one text box, click a button to display the text on a button to the text box.

Traditional practices

To solve such a simple problem, the traditional method is to use one sentence. Double-click the Button and write the following line of code in the Event Response Function of The xaml. cs file:

this.textBox1.Text = button1.Content.ToString();

This method is simple, but exposes a very serious problem: this. textBox1 is a strong reference to the view element. Such code completely coupled the view and logic (if textBox1 is not a specific view object instance, this line of logic Code cannot be compiled at all, and the logic cannot be separated from the view, which is coupled ). There is no problem with such code in small software, but when the software becomes more complex, the problem arises: in large software development, everyone is working with each other to take charge of their own modules, some people are responsible for the interface design, while others are responsible for the background logic. If the code is written like this, when the new interface of the artist is not properly painted, isn't my background logic unable to be written or tested?

Separation of views and logic has long been a consensus

Separating the View Interface and logic of the software is not an invention of MVVM. In the 1980s S, MVC separated the view layer from the logic layer (coupled with the data layer, forming a classic three-tier architecture ), later, MVPs made improvements on the basis of MVC, reducing the coupling between programs again. Based on MVP, Microsoft launched a pure data-driven MVVM framework considering the features of WPF.

Here, we need to mention the data driver. MVVM converts our programming methods from the original message-driven and event-driven to more efficient data-driven, which is completely different from MVC and MVP. Therefore, ViewModel in MVVM is not equivalent to Controller and Presenter that perform logic processing in MVC and MVP. It is more like a data formatter, its task is to process various data from different sources and then provide the data to the View in a certain format.

MVVM practices

Since MVVM inherits the classic three-tier architecture, such as MVC and MVP, it certainly combines the View layer (V-View) and the logic layer (VM-ViewModel, this is just a reference to the classic concept of the logic layer. It is not suitable to translate ViewModel into a logic layer, but the business logic is usually done here, because this example is very small, it does not involve the data layer (M-Model) for the moment ).

First, create a WPF project, and add the Views and ViewModels folders to the project. As the name implies, the Views folder stores all Views, and the ViewModels folder stores the corresponding ViewModel:

<Window x: Class = "MVVMDemo. views. childWindow "... xmlns: vm = "clr-namespace: MVVMDemo. viewModels "> <Window. dataContext> <vm: ChildWindowViewModel/> </Window. dataContext>

After this is done, the View and ViewModel are bound together. However, because we need to change the display content of the TextBox after clicking the Button, we have to bind the Text attribute of the TextBox to the ViewModel, we first create a TextBox1Text attribute in ChildWindowViewModel to bind the TextBox object:

public class ChildWindowViewModel{    public string TextBox1Text { get; set; }}

Then, bind the Text attribute of textBox1 with it:

<TextBox Name="textBox1"  Text="{Binding TextBox1Text}" .../>
Add command (ICommand)

Now that the binding is complete, add the command. Because we cannot directly write the click Event Response in The xaml. cs file, the response to the click button is implemented through the command (ICommand.

We first add an ICommand attribute to ViewModel:

Public ICommand Button1Cmd {get {return new DelegateCommand (obj) =>{// what to do after clicking button1 is written here });}}

Then, bind the ICommand attribute with the Command attribute of button1:

<Button Content="Button1" Command="{Binding Button1Cmd}" .../>

After you click button1, the code in Button1Cmd is automatically executed. In this Button1Cmd attribute, we can see a DelegateCommand class, which is a base class that is frequently used in MVVM. Because ICommand is just an interface, DelegateCommand helps us do some very basic public things in MVVM, so that we can directly write command code in Button1Cmd (to be honest, I was surprised that Microsoft didn't write this class into the class library ).

The DelegateCommand code is as follows (the source code at the end of the article also provides its generic version ):

public class DelegateCommand : ICommand    {        private Action<object> executeAction;        private Func<object, bool> canExecuteFunc;        public event EventHandler CanExecuteChanged;        public DelegateCommand(Action<object> execute)            : this(execute, null)        { }        public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)        {            if (execute == null)            {                return;            }            executeAction = execute;            canExecuteFunc = canExecute;        }        public bool CanExecute(object parameter)        {            if (canExecuteFunc == null)            {                return true;            }            return canExecuteFunc(parameter);        }        public void Execute(object parameter)        {            if (executeAction == null)            {                return;            }            executeAction(parameter);        }    }
Test command

We delete MainWindow and set StartUri in App. xaml to the path of ChildWindow so that ChildWindow can be directly started when the program is running:

<Application x:Class="MVVMDemo.App"             ...             StartupUri="Views/ChildWindow.xaml">

Add the code of a message prompt box in DelegateCommand:

Return new DelegateCommand (obj) =>{// what to do after the button1 click is written here: System. Windows. MessageBox. Show ("button1 click! "); // Test code });

Click button1. The following pop-up message box is displayed, proving that the Button-bound command is indeed passed to ViewModel.

Return new DelegateCommand (obj) =>{// what to do after clicking button1 is written here // System. Windows. MessageBox. Show ("button1 click! "); // Test code this. TextBox1Text =" button1 click! ";});

Run again. click "button1", but nothing happens. "button1 click" is not displayed in the expected textBox1 !" Why? This line of code is indeed executed, and the binding between the View and ViewModel is also completed. Why cannot the TextBox1Text be changed automatically?

The answer is: Although we have bound the ViewModel attribute to the attribute of the View element, if we want to change the attribute in the ViewModel, the corresponding elements in the View will also change, you must manually notify it.

Why do we need to manually notify Microsoft not to implement such things in the framework?

You think, there are so many elements in the View Interface, each element has so many attributes, and there are only a few attributes to be changed, I cannot add all the attributes to this function because I want to change these attributes, which is a waste of resources. In addition, it is also very easy to manually notify the code, which can be reused.

Add notification INotifyPropertyChanged

Because every attribute requires the notification interface to implement this notification interface, we can imagine that this is a task that needs to be repeated many times. In the future, we will put the implementation of this Notification interface into the base class ViewModelBase, so that all viewmodels can inherit this base class.

public class ViewModelBase : INotifyPropertyChanged    {        public event PropertyChangedEventHandler PropertyChanged;        public void RaisePropertyChanged(string propertyName)        {            if (PropertyChanged != null)            {                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));            }        }    }

Then we inherit ViewModelBase in ChildWindowViewModel and rewrite the TextBox1Text attribute:

private string textBox1Text;public string TextBox1Text{    get    {        return this.textBox1Text;    }    set    {        this.textBox1Text = value;        RaisePropertyChanged("TextBox1Text");    }}

We added RaisePropertyChanged ("TextBox1Text") in the set of TextBox1Text; this line tells the system that if I change this property, go to the "TextBox1Text" attribute in the notification interface (however, it is only responsible for the notification in place, and it does not matter what you want to do after the notification arrives ).

Run the program again and click button1. We find that textBox1 has changed as expected:

Use the same method to process button2, with the same effect.

Conclusion

So far, we have implemented the functions of the world's simplest MVVM program. Through Binding and commands, you can perform the simplest but most representative operations: Click operations on the interface and process the logic in the background. After the operations are completed, the results are updated on the interface, the two general classes DelegateCommand and ViewModelBase are also abstracted. It decouples the View and logic: we can see that our ChildWindowViewModel does not have any View-related code, so we can test it independently. Our ChildWindow. xaml. there is no line of code in the cs file, and ChildWindow is completely a view interface. You can also operate on it separately.

More importantly, as long as my ChildWindowViewModel sets the attributes bound to ChildWindow for the first time, it will no longer have to deal with views, in the future, all the operations on the View will become operations on the attributes in the ViewModel. I only need to know the logic I want to write and assign the value to that attribute, I don't care about the final form of binding that property will be presented on the interface. Isn't that what programmers dream?

It is just as free for the artist. In the past, although there were programmers and specialized artists in a large project team, most of the time the work was like this: the programmer said that a blue button is needed, and the artist switches a button to the programmer. The programmer sets this picture as the background of the button, next, you need to contact the artist for the background image to be displayed, and then write a program to adjust the color of the image style. But now it can be changed like this: the project manager said that this View should show a person's specific information (such as age and gender names), and then the artist can pick up tools like Blend, draw the entire View interface according to your own ideas, and paste it directly into the ViewModel written by the programmer like a sticker. The programmer does not need to modify anything, by specifying DataContext and binding attributes, you can use them directly. This cooperation is very exciting!

In addition, although MVVM was developed by Microsoft for the purpose of WPF, its idea is very enlightening. By binding it, the decoupling between the view and the logic layer is more thorough than that between MVP, so now, more than WPF, Android, IOS, and front-end development are working on MVVM. However, after all, MVVM is customized by Microsoft for WPF. In general, it is still the most natural and elegant Implementation of MVVM by WPF. An in-depth understanding of MVVM ideas and implementations can greatly help improve the level of WPF programming. If you still use the ideas of the MFC and Winform era to write WPF programs, that is really a waste of such advanced technology as WPF, there is a kind of vision of cutting beef with a dragon knife.

Code: MVVMDemo.rar

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.