c# - WPF UserControl with Binding Mode=OneWay -


i trying make sample wpf user control (maybe better “developer control”) bindable properties. code consists of these files:

----- mainwindow.xaml ----- <window x:class="test_binding.mainwindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:testbinding="clr-namespace:test_binding"         title="mainwindow" height="350" width="525">     <stackpanel>         <testbinding:mylabelledtextbox x:name="mltb" labeltext="my custom control: mylabelledtextbox" text="{binding stringdata, mode=oneway}" />     </stackpanel> </window>  ----- mainwindow.xaml.cs ----- using system.windows;  namespace test_binding {     /// <summary>     /// interaction logic mainwindow.xaml     /// </summary>     public partial class mainwindow : window     {         public mainwindow()         {             this.datacontext = new mydataobject();             this.initializecomponent();         }     } }  ----- mydataobject.cs ----- using system.runtime.compilerservices; // callermembername using system.componentmodel; // inotifypropertychanged  namespace test_binding {     public class mydataobject : inotifypropertychanged     {         public event propertychangedeventhandler propertychanged;          private string stringdata;         public string stringdata         {             { return this.stringdata; }             set             {                 if (value != this.stringdata)                 {                     this.stringdata = value;                     this.onpropertychanged();                 }             }         }          private void onpropertychanged([callermembername] string propertyname = null)         {             if (this.propertychanged != null)             {                 this.propertychanged(this, new propertychangedeventargs(propertyname));             }         }          public mydataobject()         {             system.timers.timer t = new system.timers.timer();             t.interval = 10000;             t.elapsed += t_elapsed;             t.start();         }          private void t_elapsed(object sender, system.timers.elapsedeventargs e)         {             this.stringdata = ((this.stringdata ?? string.empty).length >= 4 ? string.empty : this.stringdata + "*");         }      } }  ----- mylabelledtextbox.xaml ----- <usercontrol x:class="test_binding.mylabelledtextbox"              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"              mc:ignorable="d"               d:designheight="300" d:designwidth="300">   <stackpanel background="yellow">     <grid>         <grid.rowdefinitions>             <rowdefinition height="auto" />         </grid.rowdefinitions>         <grid.columndefinitions>             <columndefinition width="0.5*" />             <columndefinition width="0.5*" />         </grid.columndefinitions>            <label x:name="mltblabel" grid.row="0" grid.column="0" />         <textbox x:name="mltbtextbox" grid.row="0" grid.column="1" background="yellow" text="{binding text, mode=twoway}" />     </grid>   </stackpanel> </usercontrol>  ----- mylabelledtextbox.xaml.cs ----- using system.windows; using system.windows.controls;  namespace test_binding {     /// <summary>     /// interaction logic mylabelledtextbox.xaml     /// </summary>     public partial class mylabelledtextbox : usercontrol     {         public static readonly dependencyproperty labeltextproperty =             dependencyproperty.register("labeltext", typeof(string), typeof(mylabelledtextbox),             new propertymetadata(string.empty, mylabelledtextbox.labeltextpropertychanged));         public string labeltext         {             { return (string)this.getvalue(mylabelledtextbox.labeltextproperty); }             set { this.setvalue(mylabelledtextbox.labeltextproperty, value); }         }          public static readonly dependencyproperty textproperty =             dependencyproperty.register("text", typeof(string), typeof(mylabelledtextbox),             new propertymetadata(string.empty, mylabelledtextbox.textpropertychanged));         public string text         {             { return (string)this.getvalue(mylabelledtextbox.textproperty); }             set { this.setvalue(mylabelledtextbox.textproperty, value); }         }          public mylabelledtextbox()         {             this.initializecomponent();              this.mltblabel.datacontext = this;             this.mltbtextbox.datacontext = this;             this.mltbtextbox.textchanged += new textchangedeventhandler(this.mltbtextbox_textchanged);         }          private void mltbtextbox_textchanged(object sender, textchangedeventargs e)         {             this.text = this.mltbtextbox.text; // transfer changes textbox bindable property (bindable property change notification fired)         }          private static void labeltextpropertychanged(dependencyobject d, dependencypropertychangedeventargs e)         {             ((mylabelledtextbox)d).mltblabel.content = (string)e.newvalue; // transfer changes bindable property label         }          private static void textpropertychanged(dependencyobject d, dependencypropertychangedeventargs e)         {             ((mylabelledtextbox)d).mltbtextbox.text = (string)e.newvalue; // transfer changes bindable property textbox         }     } } 

there instance of “mydataobject” class property “stringdata”, modified periodically using timer. user control bound property “stringdata”. if binding in “mainwindow.xaml” file set “twoway”, user control keeps being updated, if use “oneway” binding, user control updated single time , “propertychanged” event of instance of “mydataobject” class not fire again, because has no subscriber.

why “oneway” binding stop working after being invoked once ? code change allow both “twoway” , “oneway” bindings keep working ?

firstly.

this.mltblabel.datacontext = this; this.mltbtextbox.datacontext = this; 

noooooooooooooooo!

never. ever. ever. set datacontext code-behind. this, lose magical beauty of binding user control's dependency properties parent control. in other words, don't it.

here's should do:

give usercontrol x:name.

<usercontrol ...     x:name="usr"> 

bind usercontrol's dependency properties elements, this:

<textblock text="{binding mydependencyproperty, elementname=usr}" ... /> 

bind usercontrol's datacontext properties elements, this:

<textblock text="{binding mydatacontextproperty}"/> 

using method allow set datacontext of usercontrol in mainwindow, still able bind usercontrol's dependency properties within usercontrol. if set datacontext of usercontrol in code-behind, not able bind dependency properties.

now, onto actual problem.

all of this:

private void mltbtextbox_textchanged(object sender, textchangedeventargs e)     {         this.text = this.mltbtextbox.text; // transfer changes textbox bindable property (bindable property change notification fired)     }      private static void labeltextpropertychanged(dependencyobject d, dependencypropertychangedeventargs e)     {         ((mylabelledtextbox)d).mltblabel.content = (string)e.newvalue; // transfer changes bindable property label     }      private static void textpropertychanged(dependencyobject d, dependencypropertychangedeventargs e)     {         ((mylabelledtextbox)d).mltbtextbox.text = (string)e.newvalue; // transfer changes bindable property textbox     } 

forget it. looks you're trying round wrongdoings spoke earlier.

you should binding dependency properties instead:

<label grid.row="0" grid.column="0" text="{binding text, elementname=usr}"/> 

another issue have in mainwindow, using binding on usercontrol.

text="{binding stringdata, mode=oneway}" 

now, have set datacontext in code-behind. saying is:

bind stringdata datacontext of current control.

which in case, totally different binding mainwindow datacontext. (as have explicitly set datacontext in usercontrol).

run through mentioned earlier. there's lot learn, it's start.


Comments

Popular posts from this blog

angularjs - ADAL JS Angular- WebAPI add a new role claim to the token -

php - CakePHP HttpSockets send array of paramms -

node.js - Using Node without global install -