c# - UserControlViewModel doesn't update binded property in UserControl -
i want able change property in main window user controls view model.
this connection
- mainwindow
- i bind property view model usercontrol
- mainwindowviewmodel
- my property lies here, updated when user control property changes
- usercontrol1
- its dependency property that's binded main window view model returns value usercontrolviewmodel
- usercontrol1viewmodel
- the logic changes property (which supposed update mainwindowviewmodel) lies here.
i can binding between of them, problem when update property bottom layer (usercontrolviewmodel), not update property neither in usercontrol or in mainwindowviewmodel.
here code (i have uploaded project on google drive)
mainwindow.xaml
<window x:class="wpfapplicationviewtoviewmodel.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:wpfapplicationviewtoviewmodel" mc:ignorable="d" title="mainwindow" height="367" width="624"> <stackpanel> <local:usercontrol1 textinusercontrol="{binding datacontext.textinmainwindowviewmodel, mode=twoway, relativesource={relativesource mode=findancestor, ancestortype=window}}"> </local:usercontrol1> <button content="test mainwindow vm" command="{binding commandtestmwvm}" ></button> <separator></separator> </stackpanel> </window>
mainvindow.xaml.cs
using system.windows; namespace wpfapplicationviewtoviewmodel { /// <summary> /// interaction logic mainwindow.xaml /// </summary> public partial class mainwindow : window { public mainwindow() { initializecomponent(); this.datacontext = new mainwindowviewmodel(); } } }
mainwindowviewmodel.cs
using system; using system.windows; using system.windows.input; namespace wpfapplicationviewtoviewmodel { class mainwindowviewmodel : viewmodelbase { public string textinmainwindowviewmodel { { return _textinmainwindowviewmodel; } set { _textinmainwindowviewmodel = value; raisepropertychanged("textinmainwindowviewmodel"); } } private string _textinmainwindowviewmodel { get; set; } //test button public mainwindowviewmodel() { _commandtestmwvm = new relaycommand(new action<object>(testmwvm)); } #region [command] commandtestmwvm public icommand commandtestmwvm { { return _commandtestmwvm; } } private icommand _commandtestmwvm; private void testmwvm(object obj) { textinmainwindowviewmodel = textinmainwindowviewmodel + "mwvm"; messagebox.show("textinmainwindowmodel " + textinmainwindowviewmodel); } #endregion } }
usercontrol1.xaml (includes 2 buttons testing purposes)
<usercontrol x:class="wpfapplicationviewtoviewmodel.usercontrol1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:wpfapplicationviewtoviewmodel" mc:ignorable="d" d:designheight="300" d:designwidth="300"> <stackpanel> <button content="test uc" click="button_click"></button> <button content="test ucvm" command="{binding commandtestucvm}" ></button> </stackpanel> </usercontrol>
usercontrol1.xaml.cs
using system.windows; using system.windows.controls; using system.windows.data; namespace wpfapplicationviewtoviewmodel { /// <summary> /// interaction logic usercontrol1.xaml /// </summary> public partial class usercontrol1 : usercontrol { private usercontrol1viewmodel vm = new usercontrol1viewmodel(); public usercontrol1() { initializecomponent(); this.datacontext = vm; //http://stackoverflow.com/questions/15132538/twoway-bind-views-dependencyproperty-to-viewmodels-property //does not work because breaks binding somewhere //string propertyinviewmodel = "textinusercontrolviewmodel"; //var bindingviewmode = new binding(propertyinviewmodel) { mode = bindingmode.twoway }; //this.setbinding(textinusercontrolproperty, bindingviewmode); } //dependency property declaration public static dependencyproperty textinusercontrolproperty = dependencyproperty.register("textinusercontrol", typeof(string), typeof(usercontrol1) ); public string textinusercontrol { { return (datacontext usercontrol1viewmodel).textinusercontrolviewmodel; } set { (datacontext usercontrol1viewmodel).textinusercontrolviewmodel = value; this.setvalue(textinusercontrolproperty, value); } } private void button_click(object sender, routedeventargs e) { textinusercontrol = textinusercontrol + "uc"; messagebox.show("textinusercontrol : " + textinusercontrol); } } }
usercontrol1viewmodel.cs
using system; using system.windows; using system.windows.input; namespace wpfapplicationviewtoviewmodel { class usercontrol1viewmodel : viewmodelbase { private string _textinviewmodel; public string textinusercontrolviewmodel { { return _textinviewmodel; } set { _textinviewmodel = value; raisepropertychanged("textinusercontrolviewmodel"); } } //test button public usercontrol1viewmodel() { _commandtestucvm = new relaycommand(new action<object>(testucvm)); } #region [command] commandtestucvm public icommand commandtestucvm { { return _commandtestucvm; } } private icommand _commandtestucvm; private void testucvm(object obj) { textinusercontrolviewmodel = textinusercontrolviewmodel + "ucvm"; messagebox.show("textinusercontrolviewmodel : " + textinusercontrolviewmodel); } #endregion } }
any really appreciated because i've been trying figure out system (reading usercontrols viewmodel mainwindow) week.
to make question more clear:
textinusercontrol
<=> textinmainwindowviewmodel
: works succesfuly
textinusercontrol
=> textinusercontrolviewmodel
: works when change textinusercontrolviewmodel
, textinusercontrol
doesn't updated automatically.
is there anyway can let textinusercontrol
know textinusercontrolviewmodel
changed?
you setting usercontrol's datacontext
usercontrol1viewmodel
instance, binding textinusercontrol
property datacontext.textinmainwindowviewmodel
, resulting in looking property usercontrol1viewmodel.datacontext.textinmainwindowviewmodel
, not exist.
one of first rules of working wpf/mvvm : never set this.datacontext = x;
in code behind user-control unless intend never pass control outside value.
instead want add instance of usercontrol1viewmodel
onto mainwindowviewmodel
, , bind usercontrol.datacontext instance.
for example,
class mainwindowviewmodel : viewmodelbase { // add property public usercontrol1viewmodel usercontroldata { ... } public string textinmainwindowviewmodel { ... } public icommand commandtestmwvm { ... } }
<!-- change binding --> <local:usercontrol1 datacontext="{binding usercontroldata}" />
and rid of following in usercontrol constructor
this.datacontext = vm;
Comments
Post a Comment