您的位置:首页 > 运维架构

WPF DependencyProperty

2008-08-04 20:39 363 查看

oSection1:Briefintroduction

1.CLRpropertiesarereallyjustsafewrappersarounda
Private
membervariable:

privateintx;


publicintX


{


get{returnx;}


set{x=value;}


}


DependencyProperty(DP)ismorethanjustsimpleCLRproperties,ThefollowingtableillustratessomeofthethingsthatcanbeacheivedbytheuseofDPs:

AchievableitemsthankstoDPs

ChangeNotification

Callbacks

Propertyvaluevalidation

Propertyvalueinheritence*

Participationinanimations*

ParticipationinStyles*

ParticipationinTemplates*

Databinding

Layoutchanges*

Overridingdefaultdatavalues*

2.DeclareofDependencyProperty:

DeclareadependencyProperty(Alwayspublicstaticreadonly)

InitialisethedependencyProperty,eitherusingDependencyProperty.RegisterAttached/DependencyProperty.Register/DependencyProperty.RegisterReadOnly/DependencyPropertyRegisterAttachedReadOnly

Declareget/setpropertywrapper(seecodebelow)

publicclassMyStackPanel:StackPanel

{


publicstaticreadonlyDependencyPropertyMinDateProperty;

staticMyStackPanel()

{

MinDateProperty=DependencyProperty.Register("MinDate",

typeof(DateTime),

typeof(MyStackPanel),

newFrameworkPropertyMetadata(DateTime.MinValue,

FrameworkPropertyMetadataOptions.Inherits));

}

publicDateTimeMinDate

{

get{return(DateTime)GetValue(MinDateProperty);}

set{SetValue(MinDateProperty,value);}

}


}


Belowistheregistermethod:

publicstaticDependencyPropertyRegister(stringname,TypepropertyType,TypeownerType,PropertyMetadatatypeMetadata,System.Windows.ValidateValueCallbackvalidateValueCallback)


ThelastparameteristhedelegateofValidateValuemethod.ForPropertyMetadataparameter,weuseFrameWorkPropertyMetadata,isthetypeusedfordependencypropertymetadata,ratherthanthebase
metadata
typesPropertyMetadataor
UIPropertyMetadata
.Thisistruebothforexistingdependencypropertiesandformostcustomdependencypropertyscenarios.

publicFrameworkPropertyMetadata(objectdefaultValue,FrameworkPropertyMetadataOptionsflags,PropertyChangedCallbackpropertyChangedCallback,CoerceValueCallbackcoerceValueCallback):base(defaultValue,propertyChangedCallback,coerceValueCallback,boolisAnimationProhibited,UpdateSourceTriggerdefaultUpdateSourceTrigger)


Defaultvalues

Provideoneofthe
FrameworkPropertyMetadataOptions
values,suchasAffectsMeasure/AffectsArrange/AffectsRender/Inheritsetc

Propertychangedcallbackdelegates

Coersionvaluescallbackdelegates,canoperatevalue

Makeapropertyun-animatable

Provideoneofthe
UpdateSourceTrigger
,suchasPropertyChanged/LostFocus/Explicitetc

oSection2:HowtheDependencyPropertyregisteredanduse

DependencyPropertyClasshasastatichashtableandlisttostoretheregistereddependencyProperty,

ClassDependencyProperty

{………………

privatestaticHashtablePropertyFromName=newHashtable();

internalstaticItemStructList<DependencyProperty>RegisteredPropertyList=newItemStructList<DependencyProperty>(0x300);

…………………..}


MethodRegister

{………

DependencyPropertydp=newDependencyProperty(name,propertyType,ownerType,defaultMetadata,validateValueCallback);

………………..

PropertyFromName[key]=dp;

RegisteredPropertyList.Add(dp);

…………

if(typeMetadata!=null)

{

this.OverrideMetadata(ownerType,typeMetadata);

}


……….}


ThekeyinPropertyFromNameis“name.HashCode^ownerType.HashCode”.

TheValueofthisdictionaryistheinstanceofDependencyPropery.

ThenifclienthavenewFrameWorkMetaData,registrationwilladdthemetadataintoainstancemap,whichwillbeexplainedspecificallybelowinAddOwnermethod.

TakenoticethatthePropertyFromNamehashtableandRegisteredPropertyListarestatic,soallDPscanaccesstheseglobalhashtableandlist,andlet'sseewhatmembersareinstancemembersinDependencyPropertyclass:

ClassDependencyProperty

{

privatePropertyMetadata_defaultMetadata;

internalInsertionSortMap_metadataMap;

privatestring_name;

privateType_ownerType;

privateFlags_packedData;

privateType_propertyType;

privateDependencyPropertyKey_readOnlyKey;

privateSystem.Windows.ValidateValueCallback_validateValueCallback;

…………………

privateDependencyProperty(stringname,TypepropertyType,TypeownerType,PropertyMetadatadefaultMetadata,System.Windows.ValidateValueCallbackvalidateValueCallback)

{

FlagsuniqueGlobalIndex;

this._metadataMap=newInsertionSortMap();

this._name=name;

this._propertyType=propertyType;

this._ownerType=ownerType;

this._defaultMetadata=defaultMetadata;

this._validateValueCallback=validateValueCallback;}

…………………….

}


MostoftheinstancemembersareinitiatedinDP’sprivateconstructor.Whenregister,thefiled“_defaultMetadata”usedtostoreFrameWorkMetaData,thenwhat“_metadataMap”usedfor?Itusedtostoreothercontrols’metaData.

Now,wehaveregisteredMinDateProperty,thenifothercontrolneedtousethisproperty,itwilluseAddOwnermethodlikebelow:

publicDependencyPropertyAddOwner(TypeownerType,PropertyMetadatatypeMetadata)

{

if(typeMetadata!=null)

{

this.OverrideMetadata(ownerType,typeMetadata);

}

lock(Synchronized)

{

PropertyFromName[key]=this;

}

}


Ifregisteranewsamenameproperty,itwillhavenothingtodowithMyStackPanel.MinDatePropertyevenifuseinheritedflagandischildrenofMyStackPanel

publicpartialclassUserControlLabel:Label

{

publicstaticreadonlyDependencyPropertyMinDateProperty=MyStackPanel.MinDateProperty.AddOwner(typeof(UserControlLabel),

newFrameworkPropertyMetadata(DateTime.MinValue,FrameworkPropertyMetadataOptions.Inherits));

}


AddOwnermethodwillcallOverrideMetadatamethodtoSuppliesalternatemetadataforthisdependencypropertywhenitispresentoninstancesofaspecifiedtype,overridingthemetadatathatwasprovidedintheinitialpropertyregistration(whenregisteration,ifmetadataisnotnull,alsowillcallthismethodtoputmetadatainmap):

this._metadataMap[dType.Id]=typeMetadata;

Wecanseethismap,itskeyiscurrentDependencyObjecttype’sId,andvalueismetadata.Takeourprogramasexample:

Instancemember:_metadataMapinMyStackPanel.MindateProperty:

UserControlLabel.typeId

UserControlLabel‘sMinDateProperty.metaData

MyStackPanel.typeId

MyStackPannel’sMinDatePropertymetaData

(Note:ifinAddOwnerorregistermethod,propertyMetaData==null,forregistermethod,itwillcreateadefaultpropertyMetadatainstance,forAddOwnermethod,itwilldon’tcallOverrideMetadatamethod,_metaMapwillnobechanged,sohowUserControlLabelfindmetadataforMinDatePropertymetaData?

InMinDateProperty.GetMetaData()method,itfirstfindmetadatathroughUserControlLabel’stypeId,ifcan’tfind,tryUserControlLabel’sbasetype,ifcan’teither,returntheMinDateProperty’sdefaultpropertymetaData.)所以在写onPropertyChanged方法时候,要判断sourceasStackPanel!=null,因为一个metadata可能被其他source用到,这时候source就不是stackPanel了。

thenadd<propertyname^ownerType,propertyinstance>toHashtablePropertyFromName,nowthehashtablecontainstwoelments,keyisdifferent,butvalueissame:

Staticmember:PropertyFromNamehashtableinMinDateProperty:

MinDate^StackPanel

StackPanel’sMinDatePropertyinstancemember

MinDate^UserControl

StackPanel’sMinDatePropertyinstancemember

ThisPropertyFromNamehashtableismainlyusebythexaml->codeprocesswhichcanbefoundbyanalyzingtheDependencyProperty.FromName()methodusingreflector’s“useby”function..

namespaceSystem.Windows.Markup

internalclassBamlMapTable

{

internalDependencyPropertyGetDependencyProperty(BamlAttributeInfoRecordbamlAttributeInfoRecord)

{

if((bamlAttributeInfoRecord.DP==null)&&(bamlAttributeInfoRecord.PropInfo==null))

{

this.GetAttributeOwnerType(bamlAttributeInfoRecord);

if(bamlAttributeInfoRecord.OwnerType!=null)

{

bamlAttributeInfoRecord.DP=DependencyProperty.FromName(bamlAttributeInfoRecord.Name,bamlAttributeInfoRecord.OwnerType);}}returnbamlAttributeInfoRecord.DP;}}SomeTimesifweaddotherclass’sDPasamemberinmyclass,wecandirectlyuseoverrideMetadatamethodtooverridemetadata:

publicvoidOverrideMetadata(TypeforType,PropertyMetadatatypeMetadata)

ClassPage:Control

StaticPage

{

UIElement.FocusableProperty.OverrideMetadata(typeof(Page),newFrameworkPropertyMetadata(BooleanBoxes.FalseBox));

}

}

ThedifferencebetweenuseAddOwnermethodandoverrideMetadatamethodisthelastonedon’tneedtoadd<propertyname^ownerType,propertyinstance>toHashtablePropertyFromName.

UseOverrideMetaDatamethod意味着这个control并不想把这个Property作为自己的property,在xaml里可以直接设置了,也就是不必写.netproperty的包装,因为这个根本不是它的属性,一般用于attachedproperty或者基类的property来overridemetadata.

InDependencyPropertyClass,alsohavemethod:

publicstaticDependencyPropertyKeyRegisterReadOnly(stringname,TypepropertyType,TypeownerType,PropertyMetadatatypeMetadata,System.Windows.ValidateValueCallbackvalidateValueCallback)

Thismethodisusedtoregisteraread-onlydependencyproperty,italsowillnewaDPinstance,fillhashtableandmetamap,atlastreturnDependencyPropertyKeyclass:

publicsealedclassDependencyPropertyKey

{

//Fields

privateDependencyProperty_dp;


//Methods

internalDependencyPropertyKey(DependencyPropertydp);

publicvoidOverrideMetadata(TypeforType,PropertyMetatypeMetadata);

internalvoidSetDependencyProperty(DependencyPropertydp);


//Properties

publicDependencyPropertyDependencyProperty{get;}
}

oSection3:HowtogetandSetPropertyValue

AllWPFclasswhichusedependencypropertyshouldinheritedDependencyObjectClass,inDependencyObject,ithasmethodsSetValue(DependencyPropertydp,boolvalue)tosetValueforonedependencyPropertyandpublicobjectGetValue(DependencyPropertydp)togetValueforonedependencyProperty.(Inprogram,codewillusepropertywrappertosetandgetvalue,butinxaml,willdirectlyuseSetValue()andGetValue()method).

InDependencyObjectClass,itusesarray

privateEffectiveValueEntry[]_effectiveValues

tostorethedependencyProperty’svalue.TheEffectiveValueEntryisnotasimplevaluestructure,itincludesmuchinformationaboutthepipelinetogetvalue,youcanseeappendixpicturespecifically.

InSetValue(DependencyPropertydp,boolvalue),itfirstlygetpropertymetadataforthiscontrolfrom_metadataMapwhichIhavesaidinfrontsection.Howtogetit?Haven’tyouseethemap?ThroughtheXXXClass.typeId(PropertyMetadatametadata=this.SetupPropertyChange(dp))

SomeTimes,wedon’tknowtheinstanceofDependencyproperty,wecanalsogetitfromPropertyFromNameHashtable,usemethodbelowwhichisinDependencyPropertyclass.

[FriendAccessAllowed]

internalstaticDependencyPropertyFromName(stringname,TypeownerType).


Now,Let’ssavethevalueinto_effectiveValuesarray.Butbeforeit,therearecomplicatedthingstodo,becauseWPFcontainsmanypowerfulmechanismsthatindependentlyattempttosetthevalueofdependencyproperties.Ofcourse,astheirnameindicates,dependencypropertiesweredesignedtodependontheseprovidersinaconsistentandorderlymanner.

Thepicturebelowillustratesthefive-stepprocess(wecallitpipeline)thatWPFrunseachdependencypropertythroughinordertocalculateitsfinalvalue.Thisprocesshappensautomaticallythankstothebuilt-inchangenotificationindependencyproperties.

InSetValuemethod,itfirstlywillgetcorrespondingdependencyPropertyEffectiveValueEntry(ifalreadyhave,getit,ifnotalreadyhave,newit)._effectiveValuesisanarray,howdoIknowwhichelementismywant?_effectiveValuesarrayuseDependencyProperty’shashcodeasindex,thishashcodeiscalledDependencyProperty.GlobalIndex,itisgeneratedindependecyProperty‘sconstructor:



lock(Synchronized)

{

uniqueGlobalIndex=(Flags)GetUniqueGlobalIndex(ownerType,name);

RegisteredPropertyList.Add(this);

}

if(propertyType.IsValueType)

{

uniqueGlobalIndex|=Flags.IsValueType;

}

if(propertyType==typeof(object))

{

uniqueGlobalIndex|=Flags.IsObjectType;

}

if(typeof(Freezable).IsAssignableFrom(propertyType))

{

uniqueGlobalIndex|=Flags.IsFreezableType;

}

if(propertyType==typeof(string))

{

uniqueGlobalIndex|=Flags.IsStringType;

}

this._packedData=uniqueGlobalIndex;

GlobalIndex=(int)this._packedData)&0xffff;

}

Nextgotothepipeline,

Step1:“determineBaseValue”:

Thefollowinglistrevealstheeightprovidersthatcansetthevalueofmostdependencyproperties,inorderfromhighesttolowestprecedence:

1.Localvalue

2.Styletriggers

3.Templatetriggers

4.Stylesetters

5.Themestyletriggers

6.Themestylesetters

7.Propertyvalueinheritance

8.Defaultvalue

HereItakeinheritanceforexample;youwillseehowtheinheritanceisimplemented.Thecodeis:

if(!flag4&&metadata.IsInherited)

{

DependencyObjectinheritanceParent=this.InheritanceParent;

if(inheritanceParent!=null)

{

EntryIndexentry=inheritanceParent.LookupEntry(dp.GlobalIndex);

if(entry.Found)

{

flag4=true;

newEntry=inheritanceParent._effectiveValues[entry.Index].GetFlattenedEntry(RequestFlags.FullyResolved);

newEntry.BaseValueSourceInternal=BaseValueSourceInternal.Inherited;

}

}

}

Step2:Expression:Ifthevaluefromsteponeisanexpression(anobjectderivingfromSystem.Windows.Expression),thenWPFperformsaspecialevaluationsteptoconverttheexpressionintoaconcreteresult.

Step3:Animation:Ifoneormoreanimationsarerunning,theyhavethepowertoalterthecurrentpropertyvalue(usingthevalueafterstep2asinput)orcompletelyreplaceit.

Step4:ifinmetadata,havesetcoerceValueCallbackdelegate,willcallthisdelegatetooperatetthevalue.Thecodelike:

if((metadata.CoerceValueCallback!=null)

{

objectobj6=metadata.CoerceValueCallback(this,coersionBaseValue);

}


Step5:Whenregisterproperty,wesetValidateValueCallbackdelegate,willcalldelegatetovalidatethispropertyvalue.

(Mostoftheabove5processisinmethodbelow,evencanseeitasaneventtriggermethod:

InternalUpdateResultUpdateEffectiveValue(EntryIndexentryIndex,DependencyPropertydp,PropertyMetadatametadata,EffectiveValueEntryoldEntry,refEffectiveValueEntrynewEntry,boolcoerceWithDeferredReference,OperationTypeoperationType))

)

Afterthefivesteps,savetheEffectiveValueEntrywhichhasthevalueto_effectiveValues[DependencyProperty.GlobalIndex].

Don’tforgetwecanaddpropertyChangedCallbackdelegatetometadatawhenregestertheDP,atlastinsetValue(),ifvaluechanged,itwillcallthisdelegate:

if((isAValueChange)

{

this.NotifyPropertyChange(newDependencyPropertyChangedEventArgs(dp,metadata,isAValueChange,oldEntry,newEntry,operationType));

}



internalvoidNotifyPropertyChange(DependencyPropertyChangedEventArgsargs)

{

this.OnPropertyChanged(args);

………………………

}



ProtectedvirtualvoidOnPropertyChanged(DependencyPropertyChangedEventArgse)

{

if((e.IsAValueChange||e.IsASubPropertyChange)||(e.OperationType==OperationType.ChangeMutableDefaultValue))

{

PropertyMetadatametadata=e.Metadata;

if((metadata!=null)&&(metadata.PropertyChangedCallback!=null))

{

metadata.PropertyChangedCallback(this,e);

}

}

}


UseGetValue()methodtogetDepencyPropertyvaluefrom_effectiveValuesarrayusingDependencyProperty.GlobalIndex,ifhavenovalue,GetValuemethodwilltrytogetvaluefromdefault,orifhavesetinheritedflaginmetaData,itwilltrytogetvaluefromparent.

InDependencyObject,thereisoneusefulmethodClearValue(DependencyProperty),itcanclearthelocalvalue(becauseithashighestprecedence),andcallUpdateEffectiveValuemethodtorunthepipelinetogetvalueagain,andthismethodcancallPropertyChangeddelegatetoo.

oSection4:AttachedDependencyProperty

AttachedpropertiesarejustanotherstrainofDPs.UsingAttachedPropertiesweareabletouseDPsfromclassesthatareoutsideofthecurrentclass.

1.RegisterAttachedDP:useRegisterAttachedmethod

publicclassMyStackPanel:StackPanel

{

publicstaticreadonlyDependencyPropertyIntDataProperty=DependencyProperty.RegisterAttached("IntData",

typeof(int),

typeof(MyStackPanel),

newFrameworkPropertyMetadata(0,

FrameworkPropertyMetadataOptions.Inherits,onIntdataChange,onIntdataCoreceValue),onIntdataValidate);
}TheownerTypecanbenotDependencyObject,soRegisterAttachedwillnotcalloverrideMetaData.Because_metadataMapuseDependencyObjectType.typeIdaskey.

2.ProvidestaticGetPropertyNameandSetPropertyNamemethodsasaccessorsfortheattachedproperty.

publicclassMyStackPanel:StackPanel

{

publicstaticvoidSetIntData(UIElementelement,intvalue)

{

//actuallyDependencyObject.SetValue()

element.SetValue(IntDataProperty,value);

}

publicstaticintGetIntData(UIElementelement)

{

//actuallyDependencyObject.GetValue()

return(int)element.GetValue(IntDataProperty);

}

}


3.Useattachedproperty.

<Labelx:Name="myLabel"FontWeight="Bold"FontSize="20"Foreground="White"Panel.ZIndex="5"ab:MyStackPanel.IntData="4">


Thecorrespondingcodingaboutattachedpropertyis:


MyStackPanel.SetIntData(myLabel,4);


4.Effect.IfinMyStackPanel,IhavesetonPropertyChangedelegate,inthemethod,Icanoperatethelabelcontrolwhichhavechangedtheproperty.Inthiscodebelow,themylabel‘sbackgroundwillbesettopink.

privatestaticvoidonIntdataChange(DependencyObjecto,DependencyPropertyChangedEventArgse)

{

if(oisControl)

{

ControlsourceControl=oasControl;

sourceControl.Background=Brushes.Pink;

}

}


AttachedProperty’sfunction:

1.Canaddfunctionsforotherclassandnotchangingtheircode.Liketheupperstep4

2.Savedatato_EffectiveValue[],getitwhenneedtouseit:

<ButtonCanvas.Left=”18”Canvas.Top=”18”Background=”Orange”>Left=18,

What’sthedifferencebetweenDependencyProperty.RegisterAttached()andDependencyProperty.Register()?Justatthemetadata,RegisterAttachedmethodwillnotcallOverrideMetadatamethod,thismethodwilldotwothingswhichhavestatedinsection2,oneiscombinethebasetype’smetadatawithnewmetadata,theotherisaddmetadatatoinstancemember_metadataMap.Whytheattachepropertydon’tdothesetwothings,Ihavenotunderstoodit.

Althoughit,RegisterAttachedmethodstillwill“new”aDependencyPropertyinstance,additintostaticmember:RegisteredPropertyListandPropertyFromNamehashtablelikeRegistermethoddo

.

Wemustknowthis“IntDate”Dependencypropertyanditsvaluearebelongto“MyLabel”instance,notbelongto“MyStackPanel”instanceanymore.ThenwegettoknowwhyweshouldaddstaticGetPropertyNameandSetPropertyNamemethods.Itneeduse“MyLabel”’sSetValue()methodtostorethe“IntDate”DPanditsvalueinto“MyLabel”’s_effectiveValuesarray.

Then“MyLabel”willgetmetadatafromIntDataProperty,andtriggerthePropertyChangeCallBackandcoerceValueCallback,becausepassthe“MyLabel”instancetothesecallback,socanoperate“MyLabel”instance.



MyLabel’s_effectiveValues[]

Index=IntDataProperty.GlobalIndex

Value=4

Appendix1:



Appendix2:





Appendix3:

InregisterandAddOwnermethod,theyallwillusetheOverrideMetadatamethod:

publicstaticDependencyPropertyRegister(stringname,TypepropertyType,TypeownerType,PropertyMetadatatypeMetadata,System.Windows.ValidateValueCallbackvalidateValueCallback)

{

PropertyMetadatadefaultMetadata=null;

if((typeMetadata!=null)&&typeMetadata.DefaultValueWasSet())

{

defaultMetadata=newPropertyMetadata(typeMetadata.DefaultValue);

}

DependencyPropertyproperty=RegisterCommon(name,propertyType,ownerType,defaultMetadata,validateValueCallback);

if(typeMetadata!=null)

{

property.OverrideMetadata(ownerType,typeMetadata);

}

returnproperty;

}


OverrideMetaDatamethod:

publicvoidOverrideMetadata(TypeforType,PropertyMetadatatypeMetadata)

{

DependencyObjectTypetype;

PropertyMetadatametadata;

this.SetupOverrideMetadata(forType,typeMetadata,outtype,outmetadata);


this.ProcessOverrideMetadata(forType,typeMetadata,type,metadata);

}


Isaidinsection2,itsmainjobisaddingnewmetadatato_metadataMapstructure.ButalreadyhaveconfusingissuewhichIdon’tunderstand.

privatevoidSetupOverrideMetadata(TypeforType,PropertyMetadatatypeMetadata,outDependencyObjectTypedType,outPropertyMetadatabaseMetadata)

{

//getawrapperstructDependencyObjectTypewhichwrapetheownertype

dType=DependencyObjectType.FromSystemType(forType);


//getownertype’sdirectlybasetype’smetadata

baseMetadata=this.GetMetadata(dType.BaseType);

}


privatevoidProcessOverrideMetadata(TypeforType,PropertyMetadatatypeMetadata,DependencyObjectTypedType,PropertyMetadatabaseMetadata)

{

lock(Synchronized)

{

//setmapIhavesaidinsection2

this._metadataMap[dType.Id]=typeMetadata;

}

typeMetadata.InvokeMerge(baseMetadata,this);

typeMetadata.Seal(this,forType);

}


Theconfusingissueis“typeMetadata.InvokeMerge”method,itseemscombinethebasetype’smetadatawithcurrentmetadata:

protectedvirtualvoidMerge(PropertyMetadatabaseMetadata,DependencyPropertydp)

{

if(baseMetadata.PropertyChangedCallback!=null)

{

Delegate[]invocationList=baseMetadata.PropertyChangedCallback.GetInvocationList();

if(invocationList.Length>0)

{

System.Windows.PropertyChangedCallbacka=(System.Windows.PropertyChangedCallback)invocationList[0];

for(inti=1;i<invocationList.Length;i++)

{

a=(System.Windows.PropertyChangedCallback)Delegate.Combine(a,(System.Windows.PropertyChangedCallback)invocationList[i]);

}

a=(System.Windows.PropertyChangedCallback)Delegate.Combine(a,this._propertyChangedCallback);


this._propertyChangedCallback=a;

}

}

if(this._coerceValueCallback==null)

{

this._coerceValueCallback=baseMetadata.CoerceValueCallback;

}

}

Incode,itseemstocombinethisDP’spropertyChangeCallbackwithbaseMetaData’spropertyChangeCallback,andifthis._coerceValueCallback==null,usebaseMetadata.CoerceValueCallback.

ButIhavemadeanexperiment:

publicclassMyStackPanel:StackPanel

{

publicstaticreadonlyDependencyPropertyMinDateProperty;

staticMyStackPanel()

{

MinDateProperty=DependencyProperty.Register("MinDate",

typeof(DateTime),

typeof(MyStackPanel),

newFrameworkPropertyMetadata(DateTime.MinValue,FrameworkPropertyMetadataOptions.Inherits,onMindateChange,onMindateCoreceValue),onMindateValidate);}publicDateTimeMinDate

{

get{return(DateTime)GetValue(MinDateProperty);}set{SetValue(MinDateProperty,value);}}…………………}publicclassMyStackPanel2:MyStackPanel

{

publicstaticreadonlyDependencyPropertyMinDateProperty=DependencyProperty.Register("MinDate",

typeof(DateTime),

typeof(MyStackPanel2),newFrameworkPropertyMetadata(DateTime.MinValue,

FrameworkPropertyMetadataOptions.Inherits,onMindateChange2),onIntdataValidate);

publicnewDateTimeMinDate

{

get{return(DateTime)GetValue(MinDateProperty);}set{SetValue(MinDateProperty,value);}}privatestaticvoidonMindateChange2(DependencyObjecto,DependencyPropertyChangedEventArgse)

{}}It’sapity,whensetvalueforMyStackPanel2.Mindate,itwilltriggeronMindateChange2method,itsparentMyStackPanel.onMindateChangewillnotbetriggered,sodotheonMindateCoreceValue.

So,Idon’tknowthemergeinoverrideMetadataisusedforwhat?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: