Quick start with WPF. Part 1. Binding, INotifyPropertyChanged and MVVM
3r33434. Hello! 3r33430. 3r33427.
3r33434. For various reasons, most of us use desktop applications, at least a browser :) And some of us need to write our own. In this article, I want to go over the process of developing a simple desktop application using the technology 3r339. Windows Presentation Foundation (WPF)
and using the MVVM pattern. Those who wish to continue reading please under the cat. 3r311. 3r373. 3r33430. 3r33427.
3r33434. I think it is not necessary to say that WPF is the development of Microsoft :) This technology is designed for developing desktop applications for Windows, starting with Windows XP. Why so? This is due to the fact that WPF runs on top of the .NET platform, the minimum requirements of which are Windows XP and later. Unfortunately, WPF does not work on other platforms, although there are chances that this will change in the near future: a WPF-based framework 3r317 is under development. Avalonia 3r373. . 3r33430. 3r33427.
What is special about WPF? 3r3145. 3r33427.
3r33434. The two main differences from other WPF tools for building desktop applications: 3r3-3303. 3r33427.
3r33132. The XAML markup language, designed to markup the window interface itself.
3r33132. DirectX rendering, hardware graphics acceleration.
3r33427.
3r33434. I will not go into details, because This is not exactly the topic of the article. If interested, then google XAML, WPF rendering, milcore.dll and DirectX :)
3r33427.
What is this article about? 3r3145. 3r33427.
3r33434. This article contains an example of an application built on WPF technology: 3r33430. 3r33427.
3r33132. MVVM and INotifyPropertyChanged interface. Copy of text. 3r373.
3r33427.
3r33434. I will try to orient the material of the article to the practical side in the “repeat after me” style with explanations. 3r33430. 3r33427.
What do we need to repeat the article? 3r3145. 3r33427.
3r33434. Little experience developing in C # :) At a minimum, you need to understand the syntax of the language well. You will also need a Windows machine (in the examples will be Win 10) with Visual Studio installed on it (in the examples will be 201? there is a free
Community Version). When you install VS, you will need to enable desktop development support for the .NET platform 3r-3330. 3r33427.
3r33434. 3r33430. 3r33427.
3r33434. Also in this section I will describe the creation of the project. 3r33430. 3r33427.
3r33434. Run VS, create a new project, select the type of application WPF App (.NET Framework) (you can enter in the search bar in the upper right), call it whatever you like. 3r33430. 3r33427.
3r33434. 3r3391. 3r33430. 3r33427.
3r33434. After creating a new project, the interface editor window will open, it looks like
for me. 3r33427.
3r33434. 3r3-300. 3r33430. 3r33427.
3r33434. At the bottom there is a markup editor, at the top - a preview of the window interface, but you can change the relative position of the code editor and the interface preview so that they will be arranged in a horizontal order using these buttons (to the right of the two areas): 3r33034. 3r33427.
3r33434. 3r33430. 3r33427.
3r3113. Before you start
3r33427.
3r33434. The elements of the window (also called the control of the word
Control
) Must be placed inside the container or inside another element of the type ContentControl. 3r3155. Container
- This is a special control that allows you to place within yourself several child controls and organize their mutual arrangement. Examples of containers:
3r33427.
3r33132. 3r3155. Grid 3r3416. - allows you to organize the elements in columns and rows, the width of each column or row is configured individually.
3r33132. 3r3155. StackPanel
- allows you to arrange child elements in a single row or column.
3r33427.
3r33434. There are other containers. Since the container is also a control, inside the container there can be nested containers containing nested containers and so on. This allows you to flexibly position the controls relative to each other. Also, with the help of containers, we can no less flexibly control the behavior of nested controls when resizing a window. 3r33430. 3r33427.
3r3144. MVVM and INotifyPropertyChanged interface. Copy of text. 3r3145. 3r33427.
3r33434.
The result of this example will be an application with two controls, in one of which you can edit the text, and in the other you can only view. Changes from one to another will be transferred synchronously without explicitly copying text using 3r3155. binding (binding)
. 3r33333. 3r33430. 3r33427.
3r33434. So, we have a newly created project (I called it 3r315415. Ex1 3r3-3416.), Move to the markup editor and first replace the default container (3r31515. 3r3160. 3r3161.
) With 3r3155. 3r3164. 3r33180. 3r31616. . This container will be enough, because we will need to place only two controls one above the other. We explicitly indicate how the components will be located by adding the property
Orientation = "Vertical"
. Add a couple of elements inside the panel stack: a text box and a text box. Since these controls will not contain nested code, you can describe them with a self-closing tag (see the code below). After all the above procedures, the container description code and nested controls should look like this: 3r33030. 3r33427.
3r33399. 3r33400. 3r3174.
3r3176.
3r3178.
3r33180. 3r3404. 3r3405. 3r33427.
3r33434. Now focus on the purpose of this example. We want the same text to be synchronously displayed in the text block when typing in the textbox, while avoiding the explicit text copy operation. We will need some kind of binding entity, and it is here that we come to such a thing as
binding (binding)
, which was mentioned above. Linking in WPF terminology is a mechanism that allows you to associate some properties of controls with some properties of a C # class object and perform mutual updating of these properties when one of the parts of the bundle changes (this can work in one, the other, or both sides at once). For those familiar with Qt, you can draw an analogy of slots and signals. In order not to stretch the time, let's move on to the code. 3r33430. 3r33427.
3r33434. So, for organizing the binding, you need the properties of controls and a certain property of a certain C # class. First, let's look at the XAML code. The text of both controls is stored in the Text property, so we will add a binding for these properties. This is done like this:
3r33427.
3r33399. 3r33400. 3r3197.
3r-33199. 3r3404. 3r3405. 3r33427.
3r33434. We made a binding, but for the time being it is not clear to what :) We need an object of some class and some property in this object to which the binding will be performed (as they say, which needs to be bogged down). 3r33430. 3r33427.
3r33434. So what is this class? This class is called the view model and serves as a link between the view (interface or its parts) and model (model, ie, those parts of the code that are responsible for the application logic. This allows us to separate (to some extent ) the application logic from the interface (view, view) is called 3r31515. Model-View-ViewModel pattern (MVVM) 3r33416. Within WPF, this class is also called 3r?3155. DataContext 3r31616. .3r33030.
3r33434. However, simply writing a view model is not enough. It is also necessary to somehow notify the binding mechanism that the view model property or the view property has changed. For this there is a special interface
INotifyPropertyChanged
which contains event
PropertyChanged
. We implement this interface as part of the base class 3-333415. BaseViewModel
. In the future, we will inherit all our model views from this base class so as not to duplicate the interface implementation. So, add
to the project. ViewModels
, and in this directory, add the file
BaseViewModel.cs
. We get the following project structure:
3r33427.
3r33434. 3r33430. 3r33427.
3r33434. The implementation code for the basic view model is
3r33427.
3r33399. 3r33400. using System.ComponentModel;
namespace Ex1.ViewModels
{
public class BaseViewModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged (string propertyName = "")
{
PropertyChanged? .Invoke (this, new PropertyChangedEventArgs (propertyName));
}
}
} 3r3405. 3r33427.
3r33434. Let's create for our class
MainWindow
its view model, inheriting from the base. For this in the same directory
ViewModels
create a file
MainWindowViewModel.cs
In which there will be such code:
3r33427.
3r33399. 3r33400. namespace Ex1.ViewModels
{
public class MainWindowViewModel: BaseViewModel
{
}
} 3r3405. 3r33427.
3r33434. Gorgeous! Now we need to add a property to this model that we will bind the text of our controls to. Since this is text, the type of this property should be
string
:
3r33427.
3r33399. 3r33400. public string SynchronizedText {get; set;} 3r3405. 3r33427.
3r33434. As a result, we get this code
3r33427.
3r33399. 3r33400. namespace Ex1.ViewModels
{
public class MainWindowViewModel: BaseViewModel
{
public string SynchronizedText {get; set;}
}
} 3r3405. 3r33427.
3r33434. So it seems to have done it. It remains to be bent on this property from the view and it is ready. Let's do it right now:
3r33427.
3r33399. 3r33400.
3r33333. 3r3404. 3r3405. 3r33427.
3r33434. Nishtyak, we are launching a project, we are typing text in a textbox and nothing happens))) Well, it's okay, in fact, we are going the right way, just have not reached the desired point yet. 3r33430. 3r33427.
3r33434. I propose to stop for a moment and think about what we are missing. We have a view. Viewmodel too. Properties like zabindili. The desired interface has been implemented. We did a lot of work to copy a pathetic line of text, why do we need this ???!?! 111
3r33427.
3r33434. Okay, jokes aside. We forgot to create an object view model and something else (more on that later). We have described the class itself, but it does not mean anything, because we do not have objects of this class. Ok, where you need to store a link to this object? Toward the beginning of the example, I mentioned a certain 3r3333334. DataContext
used in WPF. And so, any twist has property
DataContext
to which we can assign a link to our view model. Let's do it. To do this, open the file
MainWindow.xaml
and press F7 to open the code for this view. It is almost empty; it contains only the window class constructor. Add to it the creation of our view model and place it in
DataContext
windows (don't forget to add using with the necessary namespace):
3r33427.
3r33399. 3r33400. public MainWindow ()
{
InitializeComponent ();
this.DataContext = new MainWindowViewModel ();
} 3r3405. 3r33427.
3r33434. It was simple, but it is still not enough. Still, when you start the application, no text synchronization occurs. What else needs to be done? 3r33430. 3r33427.
3r33434. You need to trigger the event
PropertyChanged
when you change the property
SynchronizedText
and inform the view that it should follow this event. So, to trigger an event, modify the view model code:
3r33427.
3r33399. 3r33400. public class MainWindowViewModel: BaseViewModel
{
private string _synchronizedText;
public string SynchronizedText
{
get => _synchronizedText;
set
{
_synchronizedText = value;
OnPropertyChanged (nameof (SynchronizedText));
}
}
} 3r3405. 3r33427.
3r33434. What did we do here? We added a hidden field for storing text, wrapped it in an already existing property, and when changing this property, we not only change the hidden field, but also call the 3r3154 method. OnPropertyChanged
, defined in the base view model and causing the
event. PropertyChanged
, declared in the interface
INotifyPropertyChanged
, also implemented in the base view model. It turns out that every time the text changes, an event occurs. PropertyChanged
The property name of the view model that was changed is passed to it. 3r33430. 3r33427.
3r33434. Well, almost everything, finish line! It remains to indicate to the view that it should listen to the event 3r33415. PropertyChanged
:
3r33427.
3r33399. 3r33400. 3r3013.
3r3403. 3r3404. 3r3405. 3r33427.
3r33434. In addition to the fact that we indicated which trigger should be updated, we also indicated in which direction this update is being tracked: from view to view model or vice versa. Since we enter text in the textbox, we are only interested in the changes in the view, so we select the
mode. OneWayToSource
. In the case of a text blockIt is exactly the opposite: we are interested in changes in the view model in order to display them in a view, so we select the
mode. Oneway
. If we needed the changes to be tracked in both directions, it was possible not to indicate 3r3155. Mode
In general, either specify
TwoWay
obviously. 3r33430. 3r33427.
3r33434. So, run the program, type the text and voi-la! The text changes simultaneously, and we haven't copied anything anywhere! 3r33430. 3r33427.
3r33434. 3r33434. 3r33430. 3r33427.
3r33434. Thank you for your attention, to be continued. We will deal with the DataTemplate and the Command pattern. 3r33430.
3r3r434. ! function (e) {function t (t, n) {if (! (n in e)) {for (var r, a = e.document, i = a.scripts, o = i.length; o-- ;) if (-1! == i[o].src.indexOf (t)) {r = i[o]; break} if (! r) {r = a.createElement ("script"), r.type = "text /jаvascript", r.async =! ? r.defer =! ? r.src = t, r.charset = "UTF-8"; var d = function () {var e = a.getElementsByTagName ("script")[0]; e.parentNode.insertBefore (r, e)}; "[object Opera]" == e.opera? a.addEventListener? a.addEventListener ("DOMContentLoaded", d,! 1): e.attachEvent ("onload", d ): d ()}}} t ("//mediator.mail.ru/script/2820404/"""_mediator") () (); 3r33434.
It may be interesting
Here we introduce our top coupons that will help you for online shopping at discountable prices.Revounts bring you the best deals that slash the bills.If you are intrested in online shopping and want to save your savings then visit our site for best experience.