I. common attributes
First, let's discuss the attributes in. net. When we write a class, we need to define some fields to save some values.
Public ClassPerson {Public StringNAM;Public IntAge ;}
However, we will find that such a definition cannot meet our needs. For example, we need to implement some restrictions on field verification. At this time, we need to implement attributes for us. Because we can write our verification logic when setting attributes.
Public Class Person { Private String Name; Private Int Age; Public Int Age { Get { Return Age ;} Set { If (Value> 100 & Value < 0 ) Age = 100 ; Else Age = Value ;}}}
The following describes the principles of common attributes. The common attribute is only a sugar coat of the field. It cannot save the value itself. It will be compiled into the corresponding method after VS compilation (because the MethodBoth static and non-static files have only one copy in the memory.So even if we create multiple instances, our memory will not increase ).
Ii. Dependency attributes
Dependency attribute is a special property in WPF and an upgraded version of common attributes. Because its value depends on other objects, it can have no value itself, which can greatly save the memory overhead of the instance. Think about the fact that every element in WPF has dozens of attributes. If we need to initialize the attributes when creating each element, and assign values to the attributes, in this way, the memory of our system will be greatly increased.
In WPF, objects can be created without the space used to store data (that is, the space occupied by fields ), only retain the ability to obtain default values, borrow data from other objects, or allocate space in real time when data is needed. This type of object is called a dependency object) the ability to obtain data in real time depends on the Dependency Property. -- Go deep into WPF
Public ClassStudent: dependencyobject {Public Static ReadonlyDependencyproperty nameproperty = dependencyproperty. Register ("Name",Typeof(String),Typeof(Student ));}
A. the class to which the dependency property belongs must inherit the dependencyobject class,If you want to directly create the do object in XAML, You can inherit from contentcontrol.
B. Default Value: public static readonly dependencyproperty
C. The name of the Dependency Property should end with property,
D. Use the dependencyproperty. Register static method for registration.
E. Three parameters of the Register Method (1. Name of the Dependency Property package, 2. Save the value type of the Dependency Property, and 3. Specify the do type of the Dependency Property)
In fact, we have created a simple dependency attribute so that we can use it. Here is just an example. It is generally not used in this way, but wrapped in common attributes.
Student Stu =NewStudent ();//Assign a value to the dependency attribute through setvalue of the dependencyobject classStu. setvalue (nameproperty, tb1.text );//Get the dependency attribute assignment through the getvalue of the dependencyobject classTb2.text = Stu. getvalue (nameproperty). tostring ();
The setvalue of dependencyobject is used to assign values to the dependency attribute. getvalue is used to obtain the value of the dependency attribute. Here we will find that the dependency attribute can save the value, and the common attribute we mentioned above (its value is still saved in the field ).
2. Add a property package
In WPF, we use an attribute package to wrap our dependency attributes for ease of use.
Public string name { Get { return ( string ) getvalue (nameproperty) ;} set {setvalue (nameproperty, value) ;}
In this way, our dependency attributes are exposed to the outside world through an attribute package.We can use the dependency attribute when using common attributes.
3. Forced callback and verification callback
In WPF, we can directly assign values to the dependency attribute through setvalue. In this way, we cannot perform related verification when assigning values to the dependency attribute like the preceding common attribute, however, WPF provides two delegates for us to verify callback and force callback.
Verification callback (Validatevaluecallback):This callback function can accept or reject new values.It provides a callback function as a parameter of dependency. Register ().The function must point to only one method that accepts an object parameter and returns a Boolean value..If the return value is true, the request is accepted. If the return value is false, the request is not accepted.
Force callback (Coercevaluecallback): This callback function canChange the new value to a more acceptable value..This callback is generally used to handle conflicting dependency attribute values set for the same object (For example, when setting the values of maximum, minimum, and value of scrollbar .)
View code propertymetadata metadata = New Propertymetadata (); // Force callback when setting the maximum age, because the maximum age must be greater than the minimum age Private Static Object Coercemaxage (dependencyobject D, Object Value) // There are two parameters. One is the object to be applied to the value and the value to be used. {Student Stu = D As Student; If (( Int ) Value < Stu. minage) Return Stu. minage; Else Return Value ;} // Force callback when setting the age, because the value must be between the maximum age and the minimum age. Private Static Object Coerceage (dependencyobject D, Object Value) {student Stu = D As Student; If (( Int ) Value> Stu. maxage) Return Stu. maxage; Else If (( Int ) Value < Stu. minage) Return Stu. minage; Else Return Value ;} // Verification callback. If the set value does not meet the requirements, an exception is thrown. Private Static Bool Israngeable ( Object Value ){ Int I = Convert. toint32 (value ); If (I> = 0 & I < 150 ) Return True ; Else Return False ;} Public Static Readonly Dependencyproperty ageproperty = dependencyproperty. Register ( " Age " , Typeof ( Int ),Typeof (Student ), New Propertymetadata () {defaultvalue = 0 , Coercevaluecallback = New Coercevaluecallback (coerceage )}, New Validatevaluecallback (student. israngeable )); Public Int Age { Get {Return ( Int ) Getvalue (ageproperty );} Set {Setvalue (ageproperty, value );}} Public Int Maxage { Get { Return ( Int ) Getvalue (maxageproperty );} Set {Setvalue (maxageproperty, value );}} Public Static Readonly Dependencyproperty maxageproperty = Dependencyproperty. Register ( " Maxage " , Typeof ( Int ), Typeof (Student ), New Propertymetadata ( 0 ) {Coercevaluecallback = New Coercevaluecallback (coercemaxage), propertychangedcallback = New Propertychangedcallback (D, E) => {Student Stu = D As Student; Stu. coercevalue (student. ageproperty );})}); Public Int Minage { Get { Return ( Int ) Getvalue (minageproperty );} Set {Setvalue (minageproperty, value );}} Public Static Readonly Dependencyproperty minageproperty = Dependencyproperty. Register ( " Minage " , Typeof ( Int ), Typeof (Student ), New Propertymetadata ( New Propertychangedcallback (D, E) => {Student Stu = D As Student; // When the minimum age value changes, the value of the maximum age is forcibly called back. Stu. coercevalue (student. maxageproperty); Stu. coercevalue (student. ageproperty );})));
View code
In this sectionCodeI simulated a scrollbar to set three values-set the maximum and minimum values of age and age.
I used a verification callback when setting the age, so that an exception occurs when we enter an invalid age. Forced callback is used when the maximum age is set, because this ensures that the maximum age is greater than or equal to the minimum age, and I also use force callback when setting the age, this ensures that the age is between the maximum and minimum values.
The book says that the Force callback will be executed before the verification callback, But when I debug it, I find that the result is the opposite and I don't know why.
When we assign a value to the dependency attribute, the event execution sequence isCoercevaluecallback -- validatevaluecallback -- propertychangedcallback.
3. Additional attributes
An additional property means that an attribute does not belong to a certain object, but is subsequently attached to it due to a certain requirement. For example, we use grid. Row and canvas. Left for element layout. Its registration and usage are almost the same as the dependency attributes.