WPF Miscellaneous -- Binding expression and wpfbinding expression
Both the control definition and the user control will use a function-Binding ). Written Statement: element binding. This means to synchronize the bound elements. In my opinion, it is perfect to introduce this function in WPF. Programming is more specific. Especially with the MVVM mode, it is perfect. I am not an academic school. It is unrealistic to give a comprehensive explanation. Let's talk about Binding from the author's experience.
The most common usage method is that its target element is the DataContext object on the control. As follows:
<TextBlock Grid.Column="0" Text="{Binding DishName}" Style="{StaticResource TakingDishDishNameTextStyle}" />
The DataContext attribute is in the FrameworkElement class. That is to say, most of the controls have their own DataContext. Generally, we only need to set the DataContext attribute at the outermost layer. To better understand DataContext binding. The author provides a simple example. The author sets the DataContext value for the outermost Window. Also, the DataContext value is set for the internal Grid. But they are not the same object type, but the attributes are the same. As follows:
<Window x:Class="Wpf.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:aomi="http://aomiwpf.com/ModernUI" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local ="clr-namespace:Wpf" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <local:WindDataContext /> </Window.DataContext> <Grid> <Grid.DataContext> <local:GridDataContext /> </Grid.DataContext> <TextBlock Text="{Binding TestName}"></TextBlock> </Grid></Window>
Execution result:
The experiment proves that the target element of the standard binding method is DataContext. He will find the DataContext closest to the currently bound element. Let's assume that if the property TestName in the GridDataContext class is changed to TestName1, what would it look like? As follows:
1 public class GridDataContext : NotifyPropertyChanged 2 { 3 private string _testName1 ="GridDataContext"; 4 5 public string TestName1 6 { 7 set 8 { 9 10 if (this._testName1 != value)11 {12 this._testName1 = value;13 OnPropertyChanged("TestName1");14 }15 }16 get { return this._testName1; }17 }18 }
Execution result:
Sorry! I think he will go to the DataContext attribute TestName of Window. Apparently, he won't. It is also explained that he will only find it in the DataContext that is close to him. It will not be searched directly.
It is worth noting that if we only write {Binding} above, it is to bind the current DataContext. Instead of its attributes.
In the development process, we often hope that an element can be bound to the attributes of another element. If the attribute of another element changes, it will notify a single element to change together. At this time, we have to use the following method.
{Binding ElementName=SomeThingName, Path=Text}
ElementName: the name of the element.
Path: attribute of the element object.
In fact, we can think of a problem. Can binding only affect one party. This is the mode used in the binding. As follows:
{Binding ElementName=SomeThindName, Path=Text,Mode=TwoWay}
TwoWay: as a result, changes to the source or target attributes can be automatically updated to the other party.
OneWay: When the binding source (source) changes, the binding target (target) attribute is updated.
OneTime: update the binding target when the application starts or the data context changes.
OneWayToSource: update the source attribute when the target attribute is changed.
The preceding operations are commonly used. It is also relatively simple. Let's take a look at a binding expression in an open-source project. As follows:
<Button Command="{Binding Source={x:Static SystemCommands.MinimizeWindowCommand}}" ToolTip="{x:Static modernui:Resources.Minimize}" Style="{StaticResource SystemButton}"> <Button.Content> <Grid Width="13" Height="12" RenderTransform="1,0,0,1,0,1"> <Path Data="M0,6 L8,6 Z" Width="8" Height="7" VerticalAlignment="Center" HorizontalAlignment="Center" Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" StrokeThickness="2" /> </Grid> </Button.Content></Button>
I don't know. The above means that the Foreground of the Button of the parent node is bound with the Stroke of the current Path. The key lies in AncestorType. Specifies the type of the parent. Mode is a RelativeSourceMode type. It has four values. As follows.
Previusdata: used for data lists, meaning previous data items. That is, display the closed dataset. Controls are not included.
TemplatedParent: used for binding on the template.
Self: the attributes on the element itself are bound.
FindAncestor: used to find the parent element.
As long as this is explained, we can understand that RelativeSource is used to specify the relative source element. It is the target element.
In fact, the above expression may also be used. That is, an additional AncestorLevel is used to limit the depth of the parent level ). As follows:
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}, AncestorLevel=2}, Path=Name}
Note: If you want to modify the bound value, use the converter. As follows:
{Binding ElementName=SomeThindName, Path=Text,Mode=TwoWay,Converter=XXXConverter}
When developing custom controls, we often use an expression. As follows:
Width="{TemplateBinding Width}"
The above is just an abbreviation. Complete:
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"
It can be said that the above content is the most commonly used by the author. Next, let's look at some other content points bound. That is, the uncommon content.
1. StringFormat function. Similar to the string. format function. Give a column. If you want to add "¥" before the amount, you can use it. As follows:
<TextBlock Text="{Binding MoneyText, StringFormat=¥{0}}" />
If this is not the case, you have to give "$" A TextBlock for display, or change MoneyText to the string type, and then add $ in the set value. However, the double type is used here. Therefore, the StringFormat function can solve the problem of displaying "¥" perfectly.
Execution result:
2. The TargetNullValue function is used to bind the content to be displayed when the target is a null value. I will assign null to NullName as follows.
<TextBlock Text="{Binding NullName, TargetNullValue=aomi}" />
Execution result:
3. The FallbackValue function is used to bind the content to be displayed when an error occurs to the target. As follows:
<TextBlock Text="{Binding NullName, FallbackValue=aomi}" />
I will not post the execution results.
At the end of the article. This is an uncommon function-PriorityBinding. I cannot say this function. Let the readers understand it on their own. It is mainly used to display information when the loading time is large. For example, "loading..." is displayed ...". I have provided an example.
Xaml:
<Window x:Class="Wpf.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:aomi="http://aomiwpf.com/ModernUI" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local ="clr-namespace:Wpf" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <local:MainViewModel /> </Window.DataContext> <Grid> <TextBlock> <TextBlock.Text> <PriorityBinding> <Binding Path="UserName" IsAsync="True"></Binding> <Binding Path="LoadingName"></Binding> </PriorityBinding> </TextBlock.Text> </TextBlock> </Grid></Window>
ViewModel:
Public class MainViewModel: policypropertychanged {private string _ userName = "Haya"; private string _ loadingName = "loading... "; public string UserName {set {if (this. _ userName! = Value) {this. _ userName = value; OnPropertyChanged ("UserName") ;}} get {Thread. sleep (7000); return this. _ userName ;}} public string LoadingName {set {if (this. _ loadingName! = Value) {this. _ loadingName = value; OnPropertyChanged ("LoadingName") ;}get {return this. _ loadingName ;}}}
Execution result:
Seven seconds later:
The content in this chapter is relatively simple. I only talked about some common knowledge points. But that's all. For example, Binding is also related to the Binding of Xml and set functions. Readers can find their own materials.