Tuesday, August 05, 2008

Internal of DependencyProperty (1)

How to create a new DependencyProperty?
Let’s start from creating a new DependencyProperty. This example is simple, a new UserControl is created, which is named TestCtrl. In this UserControl, I create a new DependencyProperty as the following codes.
public partial class TestCtrl : UserControl
{
public static readonly DependencyProperty ContentProperty;

static TestCtrl()
{
TestCtrl.ContentProperty = DependencyProperty.Register("MyContent",
typeof(string), typeof(TestCtrl),
new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(OnContentChanged)),
new ValidateValueCallback(OnDefaultValueValidated));
}

public TestCtrl()
{
InitializeComponent();
}

public string MyContent
{
get { return (string)GetValue(TestCtrl.ContentProperty); }
set { SetValue(TestCtrl.ContentProperty, value); }
}

private static void OnContentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
MessageBox.Show(string.Format("Old Value: {0}; New Value: {1}", e.OldValue, e.NewValue));
TestCtrl current = obj as TestCtrl;
if (current != null)
{
current.TestBlock.Text = (string)e.NewValue;
}

}

private static bool OnDefaultValueValidated(object value)
{
MessageBox.Show("Validated Successfully");

return true;
}
}
It’s easy, isn’t it? Do you want to know what does the .Net do for you?
What does Register do…?
From this simple example, it’s easy to define a DependencyProperty, because .NET does a lot for you. Let’s see what it does.

When Register method is invoked, it invokes three methods internally.
1. RegisterParameterValidation. This method is going to validate the input parameters and ensure that all the arguments are set properly.
2. RegisterCommon. This method creates DependencyProperty and stores it.
3. OverrideMetadata. This method merges the PropertyMetadata with the PropertyMetadata of base type of your DependencyObject.
RegisterParameterValidation is simple, so it won’t be discussed here. In this section, I pay more attention to RegisterCommon and OverrideMetadata.
RegisterCommon
The following diagram is the sequence diagram of this method.





I am going to analyze this method step by step.
[1.3.1] it creates a FromNameKey object, which contains the name of the DependencyProperty and the owner type, this type is the class where this DependencyProperty is defined. This FromNameKey object is used as a key to store this dependency property.

[1.3.2] before any works, it first checks whether this property has been defined. PropertyFromName is a static field defined in DependencyProperty, and its type is Hashtable. Its key is FromNameKey and value is DependencyProperty.

[1.3.3] in ValidateMetadataDefaultValue method, it validates the default value of this PropertyMetadata. In our example, this default value is String.Empty. After the validating, it’ll invoke ValidateValueCallback, in our example, it is the method named OnDefaultValueValidated.

[1.3.4] if the validation is success, it creates the DependencyProperty object.

[1.3.5] PropertyMetadata::Seal is invoked, which invokes OnApply method internally. OnApply method is called when this metadata has been applied to a property, which indicates that the metadata is being sealed.

[1.3.6] the new dependency property is added in the PropertyFromName.
OverrideMetadata

When the DP(DependencyProperty) has already been added in PropertyFromName, there is one thing to do with PropertyMetadata, which is done in OverrideMetadata.


The discussion follows the same approach.


[1.1] SetupOverrideMetadata method uses owner type and PropertyMetadata that is passed in DependencyProperty constructor to get the DependencyObjectType of owner type and PropertyMetadata of the base class of current DependencyObject. DependencyObjectType represents a specific underlying system (CLR) Type of a DependencyObject. DependencyObjectType is essentially a wrapper for the (CLR) Type so that it can extend some of its capabilities.

[1.1.2] as said in step 1.1, SetupOverrideMetadata returns a PropertyMetadata object, which is for the base class of current DependencyObject. This work is done by GetMetadata method. In step 1.1, the DependencyObjectType of owner type is got, through this object, the DependencyObjectType of base type can be got, which is used by GetMetadata method to get the corresponding PropertyMetadata.
How to get the PropertyMetadata for the base class? All the PropertyMetadata objects are stored in _metadataMap field, which is defined as instance field in DependencyProperty. Notice that this field is instance field; this means that it contains the PropertyMetadata objects that belong to current object. The PropertyMetadata can be found in this field using the DependencyObjectType.Id as the key. How to use this PropertyMetadata of the base class will be discussed later.

[1.2] ProcessOverrideMetadata method stores this object in the _metadataMap field and merges the PropertyMetadata with the PropertyMetadata of the base class, which is got in step 1.1.2.

[1.2.2] InvokeMerge method merges the PropertyMetadata with the PropertyMetadata of the base class, which is got in step 1.1.2. The following values are copied from baseMetadata to current Metadata:
1. The default value;
2. PropertyChangedCallback invocation list;
3. CoerceValueCallback.

This is the whole process of registering a new DependencyProperty.

Next post, I am going to talk about the GetValue process in DependencyProperty.

1 comment:

Anonymous said...

A legjobb, hogy részt vegyenek egy versenyt az egyik legjobb blogok az interneten. Én ajánlom ezt a weboldalt!
Vimax Pills fokozása VigRX Plus metropathies Férfi Extra Erosíto Ne VigRX Plus tabletták tényleg muködik mastoidal
További információk:
pénisznövelo | pénisznövelo tabletták | Vimax Pills | Férfi Extra Pills | VigRX Plus