Simple source code analysis of DependencyObject and DependencyProperty in WPF, dependencyproperty

Source: Internet
Author: User

Simple source code analysis of DependencyObject and DependencyProperty in WPF, dependencyproperty
How to debug and view DependencyProperty in the DependencyObject of WPF is mentioned in the dependency attribute debugging of Windbg. We can see some internal implementations of DO (DependencyObject) and DP (DependencyProperty.
In this article, we will start with the source code to let everyone know how to obtain and assign values to the value of the dependency attribute in the dependent object.
Let's first look at an example of DP registration:

public class MyStateControl : ButtonBase{  public MyStateControl() : base() { }  public Boolean State  {    get { return (Boolean)this.GetValue(StateProperty); }    set { this.SetValue(StateProperty, value); }   }  public static readonly DependencyProperty StateProperty = DependencyProperty.Register(    "State", typeof(Boolean), typeof(MyStateControl),new PropertyMetadata(false));}


In the preceding Code, MyStateControl is DO and StateProperty is DP.
1. When MyStateControl is initialized, StateProperty is first executed because it is a static field. Execute the DependencyProperty. Register Method.
2. This method calls the DP constructor internally. The Code is as follows:// Create property DependencyProperty dp = new DependencyProperty (name, propertyType, ownerType, defaultMetadata, validateValueCallback ); 3. The DP construction method is as follows:Private DependencyProperty (string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, metadata) {_ name = name; _ propertyType = propertyType; _ ownerType = ownerType; _ defametametadata = defametametadata; _ validateValueCallback = validateValueCallback;
Flags packedData; lock (Synchronized) {packedData = (Flags) GetUniqueGlobalIndex (ownerType, name );
RegisteredPropertyList. Add (this );}
If (propertyType. IsValueType) {packedData | = Flags. IsValueType ;}
If (propertyType = typeof (object) {packedData | = Flags. IsObjectType ;}
If (typeof (Freezable). IsAssignableFrom (propertyType) {packedData | = Flags. IsFreezableType ;}
If (propertyType = typeof (string) {packedData | = Flags. IsStringType ;}
_ PackedData = packedData ;}
4. In the Code at, we can see that the initial packedData value is (Flags) GetUniqueGlobalIndex (ownerType, name ); GetUniqueGlobalIndex is actually obtained from the private static variable GlobalIndexCount ++ of DP.
The code below shows: [Flags] private enum Flags: int {GlobalIndexMask = 0x0000FFFF, IsValueType = 0x00010000, IsFreezableType = 0x00020000, IsStringType = 0x00040000, isPotentiallyInherited = 0x00080000, isdefavaluvaluechanged = 0x00100000, ispotentiallyusingdefavaluefactory = 0x00200000, IsObjectType = 0x00400000, // 0xFF800000 free bits}
Public int GlobalIndex {get {return (int) (_ packedData & Flags. GlobalIndexMask);} _ low 4 bits of packedData represent the StateProperty index in the entire DP array RegisteredPropertyList.

5. We can see the _ packedData member variable in the constructor. Do you still remember to use it for "How to debug dependency attributes in windbg? We use the. formats command to convert and remove the _ packedData high to get the storage index of DP in DO. Through points 4th and 5th, I think you have learned about DP registration.

Next, let's look at how DO gets the DP value and how to set the DP value.
6. First, let's talk about how to set DP for DO. The Code is similar:
set { this.SetValue(StateProperty, value); } 
 
We can see that we use the SetValue of DO to set the value for DP.
 
7. 
The internal implementation of SetValue is as follows:Private void SetValueCommon (DependencyProperty dp, object value, PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, OperationType operationType, bool isInternal ){...... EntryIndex entryIndex = LookupEntry (dp. GlobalIndex );...... 
According to the GlobalIndex of DP, DO finds EntryIndex in the _ effectiveValues array. EntryIndex contains the corresponding index and Value. If no Value is found, insert it in _ effectiveValues and return the index. 
(If you are interested, see the implementation of LookupEntry) 
Find in the array, and then assign values to the array. The code is similar (more complex than the following ):If (entryIndex. Found) {newEntry = _ effectiveValues [entryIndex. Index];} 
Call UpdateEffectiveValue to send a notification of attribute change. (There are other Coerce-related codes, which are not described at the moment) 
// Fire change notification yypropertychange (new DependencyPropertyChangedEventArgs (dp, metadata, isAValueChange, oldEntry, newEntry, operationType); Through the above, we can understand the implementation of dependency attribute assignment in dependency objects, let's take a look at the values. 
8. 
DO obtains the DP value. The Code is similar: 
 
get { return (Boolean)this.GetValue(StateProperty); }

9. The internal implementation of GetValue is as follows:Public object GetValue (DependencyProperty dp ){...
// Call Forwarded return GetValueEntry (LookupEntry (dp. GlobalIndex), dp, null, RequestFlags. FullyResolved). Value ;}
We can see that we first find the DP index, and then find the corresponding value from the _ effectiveValues array. The code is similar to the following:
Entry = _ effectiveValues [entryIndex. Index];
(Of course, some values are processed with priority, and the correct values are obtained)


OK. Let's look back to the steps for viewing the value of the Dependency Property of the dependency object in Windbg. 1. get the value of the dependent object; 2. get the value of the dependency attribute; 3 get the GlobalIndex of the dependency attribute; 4. locate the value of the corresponding index based on _ effectiveValues in the GlobalIndex dependency object. DO you know more about some implementations of DP and DO?

Copyright Disclaimer: This article is an original article by the blogger. You are welcome to reprint it. Please sign it only.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.