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