wpf - DependencyProperty Registration in ViewModel -
i finding lot of discussions viewmodels , properties compare 2 approches: implementation of inotifypropertychanged or implementation via dependency properties.
while doing inotifypropertychanged lot (and it's working) having difficulties implementing dp-approach.
when registering dp in viewmodel this
public static readonly dependencyproperty somepropertyproperty = dependencyproperty.register("someproperty", typeof(string), typeof(myusercontrol));
and trying use somewhere with:
<mynamespace:myusercontrol someproperty="{binding ...}"/>
there compiler error:
the property 'someproperty' not exist in xml namespace 'clr-namespace:mynamespace'.
what doing wrong??
edit1
the viewmodel looks this:
public class myusercontrolvm : dependencyobject { public string someproperty { { return (string)getvalue(somepropertyproperty); } set { setvalue(somepropertyproperty, value); } } public static readonly dependencyproperty somepropertyproperty = dependencyproperty.register("someproperty", typeof(string), typeof(myusercontrol)); }
have implemented standard property accessors? complete dp signature looks this:
public static readonly dependencyproperty propertynameproperty = dependencyproperty.register("propertyname", typeof (propertytype), typeof (myuserviewmodel), new propertymetadata(default(propertytype))); public propertytype propertyname { { return (propertytype) getvalue(propertynameproperty); } set { setvalue(propertynameproperty value); } }
then code should work. 1 more info regarding dp's vs. inotifypropertychanged: me, main tradeoff speed vs. readability. it's pain littering viewmodels dependency property declarations, gain 30% speed in notification pipeline.
edit:
you register property on view's type, should viewmodel's type, i.e.
public static readonly dependencyproperty propertynameproperty = dependencyproperty.register("propertyname", typeof (propertytype), typeof (myuserviewmodel), new propertymetadata(default(propertytype)));
instead of
public static readonly dependencyproperty propertynameproperty = dependencyproperty.register("propertyname", typeof (propertytype), typeof (myusercontrol), new propertymetadata(default(propertytype)));
edit 2:
ok, you're mixing here: can have dependency properties both, on viewmodel , view. former, define dp in control's codebehind (i.e. myusercontrol.xaml.cs). latter define in viewmodel have shown above. problem code lies in usage:
you trying bind value of datacontext
property called someproperty
on view:
<mynamespace:myusercontrol someproperty="{binding somepropertybindingvalue}"/>
as you've defined dependency property on view model, there no property someproperty
on view, hence compiler error. make above usage work, need put dp in view's codebehind , define normal property somepropertybindingvalue
on viewmodel.
to define dp on viewmodel , use in view, need bind property:
<mynamespace:myusercontrol width="{binding someproperty}"/>
supposed you've wired viewmodel , view correctly, bind views width viewmodel's property someproperty
. now, if someproperty
set on viewmodel, ui update, though haven't implemented inpc.
edit 3:
from understand problem - desired behavior - need bind 1 dependency property on control 2 properties on separate viewmodels: 1 property on mainwindowvm should bound usercontrol , - usercontrol - viewmodel (usercontrol1vm). there bit of twist in design here , without knowing exact context, don't see why couldn't handle property synch on viewmodel level:
i let viewmodels more or less resemble nested structure of view:
say have view (pseudo-code):
<window> <usercontrol1 /> </window>
let data context of window mainwm, whereever comes from, not proper xaml(!):
<window datacontext="[mainvm]"> <usercontrol1 /> </window>
question 1 is, why user control need it's own viewmodel? bind *mainvm*s property 'someproperty':
<window datacontext="[mainvm]"> <usercontrol text="{binding someproperty}" /> </window>
ok, have agood reason why need usercontrolviewmodel has it's own property 'ucsomeproperty':
public class usercontrolvm { public string ucsomeproperty { get; set; } // let inpc etc. implemented }
add usercontrolvm property mainvm:
public class mainvm { public usercontrolvm usercontrolvm { get; set; } // inpc etc. }
now, can set binding:
<window datacontext="[mainvm]"> <usercontrol datacontext="{binding usercontrolvm}" text="{binding ucsomeproperty}" /> </window>
last, again without knowing specific case , whether makes sense, let's want property on 'mainvm' in synch property on user control's viewmodel's property:
public class mainvm { public string someproperty { { return usercontrolvm.ucsomeproperty; } set { usercontrolvm.ucsomeproperty = value; } } public usercontrolvm usercontrolvm { get; set; } // inpc etc. public mainvm() { usercontrolvm = new usercontrolvm(); usercontrolvm.notifypropertychanged += usercontrolvm_propertychanged; } private void usercontrolvm_propertychanged(object sender, blaargs e) { if (e.propertyname == "ucsomeproperty") raisepropertychanged("someproperty"); } }
you use binding this, example:
<window datacontext="[mainvm]"> <usercontrol datacontext="{binding usercontrolvm}" text="{binding ucsomeproperty}" /> <textblock text="{binding someproperty}" /> </window>
someproperty on mainvm , ucsomeproperty on usercontrolvm same , available on both viewmodels. hope helps...
Comments
Post a Comment