Overview of WPF Data binding
Data binding: The process of establishing a connection between the application UI and the business logic. If the binding is set correctly and the data provides proper notification, the visual elements bound to the data automatically reflect the changes when the value of the data changes. Data binding may also mean that the underlying data can be automatically updated to reflect changes if the external representation of the data in the visual element changes.
For example, if a user edits a value in a TEXTBOX element, the underlying data value is automatically updated to reflect the change.
1. Data binding involves two aspects:
One is the binding source and one is the binding target. The binding source is the source data used by the control bindings, which is the control that the data displays.
2. For a binding source, the following four types can be in WPF:
CLR object: Can be bound to a exposed property, child property, indexer of a CLR class.
ADO. NET objects: such as DataTable, DataView, and so on.
XML file: Parsing using XPath.
DependencyObject: Binds to its dependency property, which is the control-bound control.
For a binding target, it must be a dependencyobject in WPF that binds data to its dependency property.
second, the pattern of binding
1. Depending on the direction of the data flow, data binding in WPF is divided into the following four categories:
OneWay binding: Changes to the Source property automatically update the target property, but changes to the target property do not propagate back to the source property. This binding type applies to situations where the bound control is an implicitly read-only control.
TwoWay binding: Changes to the Source property automatically update the target property, and changes to the target property automatically update the Source property. This binding type applies to editable forms or other fully interactive UI scenarios.
OneWayToSource is the opposite of oneway; it updates the Source property when the target property changes.
Onetime binding: This binding causes the Source property to initialize the target property, but does not propagate subsequent changes.
Note: If you do not need to monitor changes to the target property, using the oneway binding pattern avoids the overhead of twoway binding mode.
Most properties default to OneWay bindings, but some dependency properties, typically properties of the control that the user can edit, such as the Text property of the TextBox and the IsChecked property of the CheckBox, default to TwoWay binding.
If you want to know whether a dependency property binding is one-way or bidirectional by default, you can use GetMetaData to get property metadata for the property, and then check the Boolean value of the Bindstwowaybydefault property.
Sample code:
Copy Code code as follows:
<page x:class= "Wpfdemo.page1"
Xmlns= "Http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x= "Http://schemas.microsoft.com/winfx/2006/xaml"
Title= "Page1" horizontalalignment= "Center" >
<grid name= "gridtable" height= "360" background= "Silver" >
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<columndefinition width= "130" ></ColumnDefinition>
<columndefinition width= "></ColumnDefinition>"
<columndefinition width= "></ColumnDefinition>"
</Grid.ColumnDefinitions>
<label width= "130" height= "grid.row=" "0" grid.column= "0" name= "Label1" >TwoWay</Label>
<textbox width= "height=" "grid.row=" 0 "grid.column=" 1 "name=" textBox4 "text=" {Binding elementname= Scrollbar1,path=value,mode=twoway} "/>
<label width= "130" height= "grid.row=" "1" grid.column= "0" name= "Label2" >OneWay</Label>
<textbox width= "height=" "grid.row=" 1 "grid.column=" 1 "name=" TextBox1 "text=" {Binding elementname= SCROLLBAR1, Path=value,mode=oneway} "/>
<label width= "130" height= "grid.row=" "2" grid.column= "0" name= "label3" >OneWayToSource</Label>
<textbox width= "height=" "grid.row=" 2 "grid.column=" 1 "name=" TextBox2 "text=" {Binding elementname= SCROLLBAR1, Path=value,mode=onewaytosource} "/>
<label width= "130" height= "grid.row=" "3" grid.column= "0" name= "label4" >OneTime</Label>
<textbox width= "height=" "grid.row=" 3 "grid.column=" 1 "name=" TextBox3 "text=" {Binding elementname= SCROLLBAR1, path=value,mode=onetime} "/>
<scrollbar value= "minimum=" 0 "grid.rowspan=" 4 "grid.row=" 0 "grid.column=" 2 "maximum=" Name= "ScrollBar1" Width= "height=" {Binding elementname=gridtable,path=height} "/>
</Grid>
</Page>
Based on the results of the program implementation, we can get the following conclusions:
For oneway bindings: The data displayed in the interface can vary with the value of the data source, but changing the interface's data does not affect the data source.
For TwoWay bindings: Data displayed in the interface and data sources can be displayed and updated in two directions.
For OneWayToSource bindings: The initial interface's data is empty, and changing the interface's data can affect the value of the data source, but changing the data source value is not reflected in the interface.
For onetime bindings: The initial value of the data source displayed in the interface, changing the value of the data source does not change the interface's data display, and changing the interface's data does not affect the data source.
binding target values affect binding source value conditions
Question: Is the value of the binding source updated while you are editing the text, or is it not updated until you finish editing the text and remove the mouse pointer from the text box? Or do you need to update it in a manual update?
1. The UpdateSourceTrigger property is the reason for determining the trigger source update.
The point of the right arrow in the following illustration shows the role of the UpdateSourceTrigger property:
TwoWay and OneWayToSource are bound by the binding target to the binding source direction, and if the value change that implements the binding target affects the value of the binding source, you only need to set the UpdateSourceTrigger value of the appropriate control binding, with a value of three:
PropertyChanged: Updates the binding source immediately when the binding target property changes.
LostFocus: Updates the binding source when the bound target element loses focus.
Explicit: The binding source is updated only when the Updatesource method is invoked.
Note: The default value of the UpdateSourceTrigger value for most dependency properties is propertychanged, and the default value for the Text property is LostFocus.
2. Example
Copy Code code as follows:
Xaml:
<page x:class= "Wpfdemo.changed"
Xmlns= "Http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x= "Http://schemas.microsoft.com/winfx/2006/xaml"
title= "Changed" >
<grid name= "gridtable" height= "background=" Silver ">"
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<columndefinition width= "></ColumnDefinition>"
<columndefinition width= "></ColumnDefinition>"
<columndefinition width= "></ColumnDefinition>"
</Grid.ColumnDefinitions>
<textblock grid.row= "0" width= "height=" grid.column= "0" name= "Label1" text= "propertychanged:" ></ Textblock>
<textblock grid.row= "1" width= "height=" grid.column= "0" name= "Label2" text= "LostFocus:" ></textblock >
<textblock grid.row= "2" width= "height=" grid.column= "0" name= "label3" text= "Explicit:" ></textblock >
<textbox grid.row= "0" width= "height=" "text=" {Binding path=username,mode=twoway,updatesourcetrigger= propertychanged} "grid.column=" 1 "name=" TextBox1 "/>
<textbox grid.row= "1" width= "height=" "text=" {Binding path=username,mode=twoway,updatesourcetrigger= LostFocus} "grid.column=" 1 "name=" TextBox2 "/>
<textbox grid.row= "2" width= "height=" "text=" {Binding path=username,mode=twoway,updatesourcetrigger= EXPLICIT} "grid.column=" 1 "name=" txtexplicit "/>
<textblock grid.row= "3" width= "height=" "grid.column=" 0 "name=" lblresult "text=" Result: "></TextBlock>
<textblock grid.row= "3" width= "height=" "grid.column=" 1 "name=" Lbldisplay "text=" {Binding Path=username,mode =oneway} "></TextBlock>
<button name= "btnchanged" width= "" height= "" grid.row= "3" grid.column= "2" >Explicit</Button>
</Grid>
</Page>
Copy Code code as follows:
C#:
Namespace Wpfdemo
{
public partial class Changed:page
{
#region Properties
Public Usermodel CurrentUser
{
Get;set;
}
#endregion
#region Constructor
Public Changed ()
{
InitializeComponent ();
This. Loaded + = new Routedeventhandler (changed_loaded);
This.btnChanged.Click + = new Routedeventhandler (Btnchanged_click);
}
#endregion
#region changed_loaded
void Changed_loaded (object sender, RoutedEventArgs e)
{
This. CurrentUser = new Usermodel () {username= "SWD"};
This. DataContext = this. CurrentUser;
}
#endregion
#region btnLogon_Click
void Btnchanged_click (object sender, RoutedEventArgs e)
{
This.txtExplicit.GetBindingExpression (Textbox.textproperty). Updatesource ();
}
#endregion
}
public class Usermodel
{
public string UserName
{
Get;set;}
}
}
Program execution results as described above.
Iv. Data-Provider
1. XmlDataProvider:
XmlDataProvider access to XML data is available in the following three ways:
You can embed inline XML data using the XmlDataProvider class.
You can set the Source property to the Uri of the XML data file.
You can set the Document property to XmlDocument.
Note: When the Xmldocument.nodechanged event occurs, XmlDataProvider performs a full refresh of all bindings. A specific node is not optimized.
By default, the Xmldataprovider.isasynchronous property is set to true, which means that by default XmlDataProvider retrieves data and asynchronously generates a collection of XML nodes.
The following is an introduction to displaying XML data using the three methods described above:
Example
Copy Code code as follows:
Xaml:
<page x:class= "Wpfdemo.xmlbinding"
Xmlns= "Http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x= "Http://schemas.microsoft.com/winfx/2006/xaml"
Title= "xmlbinding" xmlns:local= "Clr-namespace:wpfdemo" >
<Page.Resources>
<xmldataprovider x:key= "XmlFile" source= "Students.xml" xpath= "/students" ></XmlDataProvider>
<xmldataprovider x:key= "Innerxmlstu" xpath= "/students" >
<x:XData>
<students xmlns= "" >
<Student><name>swd</name></Student>
<Student><name>awd</name></Student>
<Student><name>asd</name></Student>
</Students>
</x:XData>
</XmlDataProvider>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<columndefinition width= "></ColumnDefinition>"
<columndefinition width= "></ColumnDefinition>"
</Grid.ColumnDefinitions>
<textblock grid.row= "0" grid.column= "0" height= "+" width= "M" text= "Reference XML file" ></TextBlock>
<textblock grid.row= "1" grid.column= "0" height= "a" width= "M" text= "Embedded xml" ></TextBlock>
<textblock grid.row= "2" grid.column= "0" height= "+" width= "M" text= "Dynamic XML" ></TextBlock>
<listbox name= "lisbxmlfile" grid.row= "0" grid.column= "1" height= "width=" "itemssource=" {Binding source={ StaticResource Xmlfile},xpath=student/name} ">
</ListBox>
<listbox name= "Lisbinnerxml" grid.row= "1" grid.column= "1" height= "width=" "itemssource=" {Binding source={ StaticResource Innerxmlstu},xpath=student/name} ">
</ListBox>
<listbox name= "Lisbxmldoc" grid.row= "2" grid.column= "1" height= "width=" "itemssource=" {Binding xpath= Student/name} ">
</ListBox>
</Grid>
</Page>
Copy Code code as follows:
Xml:
<?xml version= "1.0" encoding= "Utf-8"?>
<Students>
<Student>
<name>swd</name>
<score>110</score>
</Student>
<Student>
<name>asd</name>
<score>120</score>
</Student>
<Student>
<name>awd</name>
<score>130</score>
</Student>
</Students>
From the above example I think we should be very easy to understand and apply.
2. ObjectDataProvider:
ObjectDataProvider enables you to create objects in XAML that can be used as binding sources and provides you with the following properties to execute a query on an object and bind to the result.
Use the Constructorparameters property to pass parameters to the object's constructor.
Use the MethodName property to invoke a method.
Use the Methodparameters property to pass the argument to the method. You can then bind to the result of the method.
Use objecttype to specify the object that will provide the data binding source.
Use the ObjectInstance property to specify an existing object instance as the source
Note: You can also use the Isasynchronous property to specify whether object creation is performed on a worker thread or in the active context. That is, whether to retrieve data asynchronously.
Example:
Copy Code code as follows:
Xaml:
C#:
Namespace Wpfdemo
{
#region Cobjectdataprovider
public partial class Cobjectdataprovider:page
{
Public Cobjectdataprovider ()
{InitializeComponent ();}
}
#endregion
#region Country
public class Country
{
#region Name
public string Name
{Get;set;}
#endregion
#region Provincelist
Public list<province> Provincelist
{Get;set;}
#endregion
#region getallcity
public static list<country> getallcity ()
{
return new list<country>{
New Country
{
Name = "China",
Provincelist = new List<province>
{
New province{name= "Fujian province",
Citylist=new list<city>{new city{name= "Fuzhou"},new city{name= "Xiamen City"},new city{name= "Zhangzhou"},new City{Name= "Quanzhou"}
},
New Province{name= "Jiangsu province",
Citylist=new list<city>{
New City{name= "Suzhou"},new city{name= "Nanjing"},new city{name= "Yangzhou"},new city{name= "Wuxi"}}
},
New Province{name= "Jiangxi province",
Citylist=new list<city>{new city{name= "Nanchang"},new city{name= "Jiujiang"}}}
}
};
}
#endregion
}
#endregion
#region Province
public class Province
{
#region Name
public string Name
{Get;set;}
#endregion
#region CityList
Public list<city> CityList
{Get;set;}
#endregion
}
#endregion
#region City
public class city
{
#region Name
public string Name
{Get;set;}
#endregion
}
#endregion
}
V. Type conversion and data validation
1. IValueConverter interface
Provides a way to apply custom logic to bindings.
At binding time, the data source object to the target object (or to the target object to the data source object) may require some kind of conversion. Only the IValueConverter interface custom value Converter can be implemented.
Interface Prototype Definition:
public interface IValueConverter
{
Object Convert (object value, Type targettype, object parameter, CultureInfo culture);
Object Convertback (object value, Type targettype, object parameter, CultureInfo culture);
}
The parameter value is the value to convert, Typetarget is the converted value type, and parameter is the parameter passed by the converterparameter of the binding class.
Convert method: The data binding engine calls this method when it propagates a value from the binding source to the binding target.
Convertback method: This method is called when the data binding engine propagates a value from a binding target to a binding source.
The Valueconversion property is used to tell the type of source and target data that the custom converter class can convert (the Valueconversion property will be seen in the later example).
2. ValidationRule class
Provides a way to create a custom rule to check the validity of user input.
ValidationRule: base class for all custom validation rules. Provides a portal for user-defined validation rules.
Exceptionvalidation: Represents a rule that checks for exceptions that are thrown during the binding source property update. It is a built-in rule that checks for exceptions that are thrown during the binding source property update.
Validationresult: The presentation of data validation results. After the Validate method of the ValidationRule object is executed, the validationresult is used to represent the result of the validation. This contains the error message-errorcontent, and whether the data is valid-isvalid. Validresult is a valid instance of Validationresult.
ValidationError: Represents a validation error that is created by the binding engine when ValidationRule reports validation errors.
Copy Code code as follows:
Xaml:
<page x:class= "Wpfdemo.typeconvertandvalidationrule"
Xmlns= "Http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x= "Http://schemas.microsoft.com/winfx/2006/xaml"
Title= "Typeconvertandvalidationrule"
xmlns:src= "Clr-namespace:wpfdemo" >
<grid height= "width=" "360" background= "Silver" >
<Grid.RowDefinitions>
<RowDefinition>
</RowDefinition>
<RowDefinition>
</RowDefinition>
<RowDefinition>
</RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition>
</ColumnDefinition>
<ColumnDefinition>
</ColumnDefinition>
</Grid.ColumnDefinitions>
<textblock height= "width=" text= "Birthday" grid.row= "0" grid.column= "0" ></TextBlock>
<textbox name= "Txtbirthday" height= "width=" grid.row= "0" grid.column= "1" >
<TextBox.Text>
<binding path= "Birthday" updatesourcetrigger= "LostFocus" mode= "TwoWay" >
<Binding.ValidationRules><src:ValidationDateTimeRule/></Binding.ValidationRules>
<Binding.Converter><src:MyConverterOfBirthFormat/></Binding.Converter>
</Binding>
</TextBox.Text>
<TextBox.ToolTip>
<binding relativesource= "{RelativeSource Self}" path= (Validation.errors) [0]. Errorcontent "></Binding>
</TextBox.ToolTip> </TextBox>
<textblock height= "width=" grid.row= "1" text= "{Binding path=birthday,mode=oneway}" grid.column= "1" > </TextBlock>
<textblock height= "width=" text= "e-mail format check" grid.row= "2" grid.column= "0" ></TextBlock>
<textbox height= "width=" grid.row= "2" grid.column= "1" >
<TextBox.Text>
<binding path= "EMail" >
<binding.validationrules><exceptionvalidationrule/></binding.validationrules>
</Binding> </TextBox.Text>
<TextBox.ToolTip>
<binding relativesource= "{RelativeSource Self}" path= (Validation.errors) [0]. Errorcontent "></Binding>
</TextBox.ToolTip> </TextBox>
</Grid>
</Page>
Copy Code code as follows:
C#:
Namespace Wpfdemo
{
#region Typeconvertandvalidationrule
public partial class Typeconvertandvalidationrule:page
{
Public Typeconvertandvalidationrule ()
{
InitializeComponent ();
This. DataContext = new UserInfo {Name = "swd", Birthday =system.convert.todatetime ("1987/10/21"), EMail = "swd@126.com"};
}
}
#endregion
#region UserInfo
public class UserInfo
{
#region Name
public string Name
{Get;set;}
#endregion
#region Birthday
Public DateTime Birthday
{Get;set;}
#endregion
#region EMail
private string Email;
public string EMail
{
Get
{return email;}
Set
{
This.email = value;
Regex r = new Regex (@ "^\w+" ([-+.] \w+) *@\w+ ([-.] \w+) *\.\w+ ([-.] \w+) *$ ");
if (!r.ismatch (value))
{
throw new ApplicationException ("email format is wrong!") ");
}
}
}
#endregion
}
#endregion
Binding Collection Objects
1. Icollectionview interface
Allows collections to have the current records management, custom sorting, filtering, and grouping features. such as sorting, grouping, filtering, navigating, and other custom views, and this does not affect the actual storage of your background data.
2. ObservableCollection <T> class
Represents a Dynamic data collection that provides notifications when items are added, removed, or the entire list is refreshed.
3. Overview of the WPF MVVM
MVVM (Model-view-viewmodel) is evolved from MVC,MVP. MVVM separates the logic from the interface and frees the business logic.