1. Binding Introduction
WPF binding can establish a connection between the source data object and the UI control to implement one-way or two-way change notification, so as to achieve better separation of business logic and UI. The common mode is:Bind the target property (which must be a dependency property) of the target object (usually a XAML element control) to the data source (CLR object, ADO) by binding the object (binding object instance.. NET data tables, XML data, etc ).For example, we can bind textbox1.text to personal. Name.
In the following example, we can observe the following automatic behavior.
(1) Click btnset to modify the source object. The target property textbox1.text is automatically changed.
(2) Modify textbox1.text and click btnget. The source object is automatically modified.
Window. XAML
<Window X: class = "learn. WPF. window1"
Xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "window1" Height = "276" width = "360" windowstartuplocation = "centerscreen">
<Grid>
<Stackpanel>
<Textbox X: Name = "textbox1"/>
<Button X: Name = "btnget" content = "get name" Click = "buttonclick"/>
<Button X: Name = "btnset" content = "Set Name" Click = "buttonclick"/>
</Stackpanel>
</GRID>
</WINDOW>
Windows. XAML. CS
Class mydata: dependencyobject
{
Public static readonly dependencyproperty nameproperty =
Dependencyproperty. Register ("name", typeof (string), typeof (mydata ),
New uipropertymetadata ("Hello, world! "));
Public string name
{
Get {return (string) getvalue (nameproperty );}
Set {setvalue (nameproperty, value );}
}
}
Public partial class window1: Window
{
Mydata data;
Public window1 ()
{
Initializecomponent ();
Data = new mydata ();
VaR binding = new binding ("name") {source = data };
This. textbox1.setbinding (textbox. textproperty, binding );
}
Private void buttonclick (Object sender, routedeventargs E)
{
If (sender = btnset)
Data. Name = datetime. Now. tostring ();
Else
MessageBox. Show (data. Name );
}
}
Obviously, this effect allows developers to focus only on business logic or UI display, greatly reducing the code association between the two.
We can also use the binding. mode attribute to specify the binding direction of the change notification. By default, it is usually two-way binding.
- Oneway: When the data source is modified, the target attribute is automatically updated. Modification to the target attribute does not affect the source object.
- Twoway: Both the data source and target attributes are updated automatically.
- Onewaytosource: Opposite to oneway, the data source is automatically updated when the target attribute is modified. Otherwise, the data source is not updated.
- Onetime: Modify the target attribute only during initialization.
Data = new mydata ();
VaR binding = new binding ("name") {source = data, mode = bindingmode. oneway };
This. textbox1.setbinding (textbox. textproperty, binding );
System. Windows. Data. bindingoperations
Class provides all the operation methods required for binding. And frameworkelement. setbinding ()
The bindingoperations. setbinding method may be more common because it can directly use dependencyobject.
Public bindingexpression frameworkelement. setbinding (dependencyproperty DP, bindingbase binding)
Public static bindingexpressionbase bindingoperations. setbinding (dependencyobject target,
Dependencyproperty DP, bindingbase binding)
Change the preceding example to bindingoperations.
Bindingoperations. setbinding (this. textbox1, textbox. textproperty, new binding ("name") {source = data });
We can use the clearbinding method to unbind the instance.
Private void buttonclick (Object sender, routedeventargs E)
{
If (sender = btnset)
Data. Name = datetime. Now. tostring ();
Else if (sender = btnclear)
Bindingoperations. clearbinding (this. textbox1, textbox. textproperty );
Else
MessageBox. Show (data. Name );
}
After you click btnclear, you will find that the bound automatic change is invalid.
2. Use binding in XAML
In XAML, we cannot use setbinding, but must use the extension tag binding instead (note that there is no extension suffix ). The extension tag can bind the target attribute to a static resource or other XAML elements (including the target element itself.
(1) bind to other elements
<Window X: class = "learn. WPF. window1"
Xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "window1">
<Grid>
<Stackpanel>
<Textbox X: Name = "textbox1"/>
<Label X: Name = "label1" content = "{binding elementname = textbox1, Path = text}"/>
</Stackpanel>
</GRID>
</WINDOW>
(2) bind to static Resources
<Window X: class = "learn. WPF. window1"
Xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "window1">
<Window. Resources>
<Contentcontrol X: Key = "text"> Hello, world! </Contentcontrol>
</Window. Resources>
<Grid>
<Stackpanel>
<Label X: Name = "label1" content = "{binding source = {staticresource text}"/>
</Stackpanel>
</GRID>
</WINDOW>
System. Windows. Data. Binding. source is not a dependency attribute, so we cannot bind it to a dynamic resource (dynamicresouce.
(3) bind to yourself
<Window X: class = "learn. WPF. window1"
Xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "window1">
<Grid>
<Stackpanel>
<Label X: Name = "label1" content = "{binding relativesource = {relativesource self}, Path = Name}"/>
</Stackpanel>
</GRID>
</WINDOW>
(4) bind to the parent element of the specified type
<Window X: class = "learn. WPF. window1"
Xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "window1">
<Grid X: Name = "grid1">
<Stackpanel>
<Label X: Name = "label1" content = "{binding relativesource = {relativesource findancestor,
Ancestortype = {X: type grid }}, Path = Name} "/>
</Stackpanel>
</GRID>
</WINDOW>
3. bind to a Common Object
WPF allows any. Net object to be used as the data binding source.
Class data
{
Public string name {Get; set ;}
}
Public partial class window1: Window
{
Public window1 ()
{
Initializecomponent ();
VaR DATA = new data {name = "Q. yuyun "};
Bindingoperations. setbinding (this. textbox1, textbox. textproperty, new binding ("name") {source = data });
}
}
However, when we modify the data source, the target attribute is automatically updated because the change notification cannot be received. To solve this problem, we need to implement the system. componentmodel. inotifypropertychanged interface for the data source object.
Public Delegate void propertychangedeventhandler (Object sender, propertychangedeventargs E );
Public interface inotifypropertychanged
{
// Events
Event propertychangedeventhandler propertychanged;
}
Let's try to modify the data type in the above example.
Class data: inotifypropertychanged
{
Private string name;
Public event propertychangedeventhandler propertychanged;
Public string name
{
Get
{
Return name;
}
Set
{
If (value! = Name)
{
Name = value;
If (propertychanged! = NULL)
{
Propertychanged (this, new propertychangedeventargs ("name "));
}
}
}
}
}
Public partial class window1: Window
{
Data data;
Public window1 ()
{
Initializecomponent ();
Data = new data {name = "Q. yuyun "};
Bindingoperations. setbinding (this. textbox1, textbox. textproperty,
New binding ("name") {source = data });
}
Protected void buttonclick (Object sender, routedeventargs E)
{
If (sender = button1)
Data. Name = datetime. Now. tostring ();
Else
MessageBox. Show (data. Name );
}
}
Now, two-way update is supported.