WPF QuickStart DataBinding (data Binding)
First look at the overview of the WPF Data binding,
Binding source can be any CLR object, or XML file, Binding target needs to have dependency properties. This allows for data Binding. Take a look at the following example,
C#
public partial class Mainwindow:window
{public
MainWindow ()
{
InitializeComponent ();
DataContext = new Person () {Name = ' Tom ', age =};
Public
class Person {public
string Name {get; set;}
public int Age {get; set;}
}
Xaml:
<Grid>
<StackPanel>
<textblock text= "{Binding Name}" margin= "10,5"/>
; TextBlock text= "{Binding age}" margin= "10,5"/>
</StackPanel>
</Grid>
Run Result:
Here are some examples to introduce the data Binding,
1. We can specify the ElementName and path properties of binding target in XAML to get the data for binding source, for example,
Xaml:
<StackPanel>
<slider x:name= "_slider" minimum= "0" maximum= "a" value=/> "<textbox"
text= "{Binding elementname=_slider,path=value}"/>
</StackPanel>
Run Result:
In the XAML code above, the slider Value property is binding to the TextBox.
By using the GIF image above, you can see that when you drag slider, the value in the TextBox changes with the value of slider, and when you enter a value in the TextBox, the value of slider changes when you press the TAB key to lose focus. This is because the default binding mode for the TextBox is TwoWay and Updatesouretrigger defaults to LostFocus. Take a look at the Bindingmode schematic below,
The
Diagram has a binding Mode,
OneWay, where the data flows from source to target,
TwoWay, data from source to target, or from target to source ,
OneWayToSource, in contrast to OneWay,
Onetime, which indicates that the value of the binding in target does not change after the data binding occurs, regardless of the data source change.
Let's illustrate the 4 binding
XAML by example:
<Grid> <Grid.RowDefinitions> <rowdefinition height= "Auto"/> < rowdefinition height= "Auto"/> <RowDefinition
height= "Auto"/> <rowdefinition height= "Auto"/>
</Grid.RowDefinitions> <!--oneway binding--> <StackPanel> <TextBlock text= "Binding mode: oneway"/> <slider x: Name= "_slider" minimum= "0" maximum= " value="/> <textbox text= "{binding elementname=_slider,path=value,mode=oneway}"/> </stackpanel> <!--onetime binding--> <stackpanel grid.row= "1" margin= "0,20" > < textblock text= "Binding mode: onetime"/> < Slider x:name= "_slider1" minimum= "0" maximum= " value="/> <textbox text= "{binding elementname=_slider1,path=value,mode=onetime}"/ > </StackPanel> <!-- Onewaytosource binding--> <!--The fontsize default value for the textbox is 12--> <stackpanel grid.row= "2" > <textblock text= "Binding mode: onewaytosource"/> < Slider x:name="_slider2" minimum= "0" maximum= " value="/> <textbox fontsize= "{Binding elementname=_slider2,path=value, mode=onewaytosource}" Text= "{binding relativesource={relativesource self},path=fontsize}"/> < /stackpanel> <!--twoway binding--> <stackpanel grid.row= "3" margin= "0,20" > <TextBlock text= "Binding mode: twoway"/> <slider x: Name= "_slider3" minimum= "0" maximum= " value="/> <textbox text= "{binding elementname=_slider3,path=value,mode=twoway}"/> &lT;/stackpanel> </Grid>
Run Result:
In the project development according to the actual need to choose different binding mode, if some data only at the start of the program display, after the face of data modification, do not need to update, you can choose onetime mode; If you show the data in real time, you can choose OneWay mode. If you need to synchronize the changes to the data, then we choose TwoWay Mode. The appropriate binding mode can optimize the performance of the program.
Next look Updatesourcetrigger,updatesourcetrigger has the following several values,
1. LostFocus, for example, when the textbox loses focus and updates source;
2. PropertyChanged, for example, when input in a textbox, source is updated synchronously;
3. Explict, need to display the call Updatesource method;
Here we look at another concept in binding converter; Look at an example where a text box displays the current temperature, and if the temperature is greater than 35, the foreground color of the text box is set to red, and if the temperature is less than 0, the display is blue;
Xaml:
<Window.Resources>
<local:temperaturetobrushcoverter hot= "cold=" 0 "x:key=" Temperaturetobrushcoverter "/>
</Window.Resources>
<Grid>
<textbox text=" width= "Height=" "
foreground=" {Binding path=text,relativesource={relativesource Self},
Converter={staticresource temperaturetobrushcoverter} "/>
</Grid>
C#:
[Valueconversion (typeof (Double), typeof (Brush))] public class temperaturetobrushcoverter : IValueConverter { public double hot { get; set; } public double cold { get; set; } public temperaturetobrushcoverter () { } Public temperaturetobrushcoverter (Double hot,double cold) :this () { Hot =
Hot
Cold = cold; &NBSP;&NBSP;&NBSP;&NBSP} public object convert (Object value, Type targettype, object parameter, cultureinfo culture) { double temp;
Brush brush = Brushes.Black; if (Double.tryparse ((string) value,out temp)) { if (temp > hot) { brush =
brushes.red; } else if (Temp < cold) {
brush = Brushes.Blue; }
return brush; &NBSP;&NBSP;&NBSP;&NBSP} public object convertback (object value,
Type targettype, object parameter, cultureinfo culture) {
throw new notimplementedexception (); &NBSP;&NBSP;&NBSP;&NBSP}}
Run Result:
Note that you want to reference converter in XAML.
Finally, let's take a look at the data validation in databinding; To see an example that binds the age of a person object to a textbox, and can modify it, ages is a meaningful value, if it is less than 0 or greater than 120, We all think it is illegal value, give the corresponding hint. Take a look at the following code:
Xaml:
<Grid> <textbox width= " height=" > <TextBox.Text> <binding path= "Age" updatesourcetrigger= "propertychanged" > <Binding.ValidationRules> <local:agevalidationrule validationstep= "Rawproposedvalue"/> </Binding.ValidationRules> </Binding> </TextBox.Text> <!--error template-- > &NBSP;&NBsp; <validation.errortemplate> <ControlTemplate> <StackPanel> <adornedelementplaceholder/ > <textblock text= "{binding [0]. Errorcontent} " foreground=" Red/> </StackPanel> </ControlTemplate> </ Validation.errortemplate> </TextBox> </Grid>
C #:
Public partial class mainwindow : window { public
MainWindow () { initializecomponent (); datacontext = new person () { Age
= 25}; &NBSP;&NBSP;&NBSP;&NBSP}} public class person { public int Age
{ get; set; }} Public class agevalidationrule : validationrule { public Override validationresult validate (Object value, cultureinfo cultureinfo) { int age; if (int. TryParse ((String) value,out age) { if (age< 0 | | age > 120) { return new
validationresult (false, "this is invalide age."); } else { return
new validationresult (True, null); } } return new validationresult (False,
"Please input valid age."); &NBSP;&NBSP;&NBSP;&NBSP}}
Run Result:
WPF QuickStart attached properties (attached property)
1. Additional properties used,
The most common use of attached properties in WPF is the placement of controls when the control is laid out, for example, there is a rectangle, Ellipse, Button in the canvas, and we need to set their position.
<Canvas>
<rectangle x:name= "_rect" fill= "LightBlue" width= "200" height= "canvas.left=" Canvas.top= "/>"
<ellipse width= "height=" fill= "lightcoral" canvas.left= "" "/>"
<button content= "I am a Button" width= "height=" canvas.left= "50" />
</Canvas>
In addition to setting dependent properties in XAML, you can also set in C # code, for example:
Canvas.setleft (_rect, 100);
Canvas.settop (_rect, 50);
Display effect:
Attached properties are easy to use.
2. Custom attached properties
Now there is a need to rotate the button,ellipse,rectangle above to a certain angle. We can do this by:
Xaml:
<Canvas> <rectangle x:name= "_rect" fill= "LightBlue" Width= "100" height= " canvas.top=" " rendertransformorigin=". 5,.5 "> <Rectangle.RenderTransform> <rotatetransform angle= "/>" < /rectangle.rendertransform> </Rectangle> <ellipse width= " height=" " fill=" Lightcoral " canvas.left=" " canvas.top=" " Rendertransformorigin= ". 5,.5" > <ellipse.rendertransform > <rotatetransform angle= "60 "/> </Ellipse.RenderTransform> </ellipse&Gt <button content= "I am a button" Width= " Height=" " canvas.left=" " canvas.bottom=" " rendertransformorigin=". 5,.5 "> <Button.RenderTransform> <rotatetransform angle= "160"/> </Button.RenderTransform> </Button> </Canvas>
The effect is as follows:
Careful you have found that the above three pieces of code basically the same, but also very long. We can use additional properties to implement, create a new Rotationhelper class, the following code:
using system.windows;
using system.windows.media; namespace useattachedproperty.helper { public class rotationhelper : dependencyobject { public
Static double getangle (dependencyobject obj) { return (double) obj.
GetValue (Angleproperty); } public Static void setangle (Dependencyobject obj, double value) { obj.
SetValue (Angleproperty, value); } public Static readonly dependencyproperty angleproperty = dependencyproperty.registerattached ("Angleproperty", typeof (Double), typeof ( Rotationhelper),
new propertymetadata (0.0,onanglechanged)); private static void onanglechanged ( Dependencyobject d, dependencypropertychangedeventargs e) { uielement element
= d as UIElement; if (element != null) { eLement.
Rendertransformorigin = new point (0.5, 0.5); element.
Rendertransform = new rotatetransform (double) e.newvalue); } }  }}
inherits DependencyObject from the Rotationhelper class, which is not only button,ellipse, but can be used by other elements that inherit from DependencyObject. The
now uses custom angle attached properties in XAML.
<window x:class= "Useattachedproperty.mainwindow" xmlns= "Http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x= "Http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d= "Http://schemas.microsoft.com/expression/blend/2008" xmlns:mc= " http://schemas.openxmlformats.org/markup-compatibility/2006 " Xmlns:helper= "Clr-namespace:useattachedproperty.helper" xmlns:
Local= "Clr-namespace:useattachedproperty" mc:ignorable= "D"
"MainWindow" height= " title=" Width= "525" > <Canvas> <rectangle x: Name= "_rect" fIll= "LightBlue" width= " height=" canvas.top= "45" helper:rotationhelper.angle= " /> <ellipse width= " height=" "100" fill= "Lightcoral" canvas.left= " canvas.top=" helper:rotationhelper.angle= "60" /> <button content= "i am a Button " width=" height= " canvas.left=" " canvas.bottom=" helper: rotationhelper.angle= "160" /> </Canvas> </Window>
The
Displays the effect at this time as it does with RenderTransform in XAML.