c# - SelectedIndex with OneWayToSource binding does not trigger -
i have problem particular xaml databinding. have 2 listboxes (master-details, listboxes have issynchronizedwithcurrentitem set true). want viewmodel know when selected item on details listbox changes: created int property on viewmodel class (i.e. can call property selind)and on details viewmodel bind way:
selectedindex="{binding mode=onewaytosource, path=selind}"
i no errors/exceptions @ runtime, binding not trigger: viewmodel's property not updated when selected item changes. if change binding mode twoway works fine, that's not need. need work onewaytosource (btw same non-working behaviour applies if bind selecteditem selectedvalue properties).
why bindings not trigger onewaytosource?
here's more complete code example, things clearer: edit: can't show real code (nda) i'll show here simpler , similar enough (the page's datacontext instance of pageviewmodel class explained later) need viewmodel class's selind property should reflect value of selectedindex in second listbox. have found alternative methods doing (event handler in code-behind or attached behaviour) right i'm curious why doesn't work onewaytosource binding.
<page> <contentcontrol x:name="maindatacontext"> <grid datacontext={binding path=masters}> <grid.columndefinitions> <columndefinition width="*" /> <columndefinition width="*" /> </grid.columndefinitions> <listbox grid.column="0" selectionmode="single" issynchronizedwithcurrentitem="true" itemssource="{binding }"> <listbox.itemcontainerstyle> ... </listbox.itemcontainerstyle> <listbox.itemtemplate> <datatemplate> .... </datatemplate> </listbox.itemtemplate> </listbox> <listbox grid.column="1" selectionmode="single" selectedindex="{binding mode=onewaytosource, elementname=maindatacontext,path=datacontext.selind}" issynchronizedwithcurrentitem="true" itemssource="{binding path=details}"> <listbox.itemcontainerstyle> ... </listbox.itemcontainerstyle> <listbox.itemtemplate> <datatemplate> .... </datatemplate> </listbox.itemtemplate> </listbox> </grid> </contentcontrol> </page>
here's sketch of view model class
public class pageviewmodel{ public observablecollection<masterclass> masters {get;set;} public int selind {get;set;} .... }
and here's masterclass, holds name , list of details
public class masterclass{ public observablecollection<detailsclass> details {get;set;} public string mastername {get;set;} .... }
i think in case, must use mode oneway
. default, have used mode twoway
.
quote msdn twoway
:
twoway binding causes changes either source property or target property automatically update other. type of binding appropriate editable forms or other fully-interactive ui scenarios. properties default oneway binding, dependency properties (typically properties of user-editable controls such text property of textbox , ischecked property of checkbox) default twoway binding. programmatic way determine whether dependency property binds one-way or two-way default property metadata of property using getmetadata , check boolean value of bindstwowaybydefault property.
mode oneway
, need
:
oneway binding causes changes source property automatically update target property, changes target property not propagated source property. type of binding appropriate if control being bound implicitly read-only. instance, may bind source such stock ticker or perhaps target property has no control interface provided making changes, such data-bound background color of table. if there no need monitor changes of target property, using oneway binding mode avoids overhead of twoway binding mode.
mode onewaytosource
:
onewaytosource
reverse
of oneway binding; updates source property when target property changes. 1 example scenario if need re-evaluate source value ui.
below diagram better understanding of the:
okay, i'll show example works me. perhaps useful you.
xaml
<window x:class="selectedindexhelp.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:selectedindexhelp" title="mainwindow" height="350" width="525" contentrendered="window_contentrendered" windowstartuplocation="centerscreen"> <window.resources> <local:selectedindexclass x:key="selectedindexclass" /> </window.resources> <grid datacontext="{staticresource selectedindexclass}"> <listbox x:name="mylistbox" borderthickness="1" width="200" height="200" borderbrush="#ce5e48" displaymemberpath="name" background="aliceblue" selectedindex="{binding myselectedindex, mode=onewaytosource}" /> <label name="selectedindex" verticalalignment="top" content="{binding myselectedindex}" contentstringformat="selectedindex: {0}" width="100" height="30" background="lavender" /> </grid> </window>
code behind
public partial class mainwindow : window { public class person { public string name { get; set; } public int age { get; set; } } private observablecollection<person> dataforlistbox = new observablecollection<person>(); public mainwindow() { initializecomponent(); } private void window_contentrendered(object sender, eventargs e) { dataforlistbox.add(new person() { name = "sam", age = 22, }); dataforlistbox.add(new person() { name = "nick", age = 21, }); dataforlistbox.add(new person() { name = "cris", age = 25, }); dataforlistbox.add(new person() { name = "josh", age = 36, }); dataforlistbox.add(new person() { name = "max", age = 32, }); dataforlistbox.add(new person() { name = "john", age = 40, }); mylistbox.itemssource = dataforlistbox; mylistbox.focus(); } } public class selectedindexclass { private int? myselectedindex = 0; public int? myselectedindex { { return myselectedindex; } set { myselectedindex = value; } } }
output
in example, there class of data - person
, these data listbox
. , class selectedindexclass
(datacontext
), contains property myselectedindex
, parameter of binding onewaytosource
.
edit:
i'm glad figured out problem. i'll try explain example, why not working elementname
case.
so, let's have code:
<contentcontrol x:name="maindatacontext"> <grid x:name="maingrid" datacontext="{staticresource selectedindexclass}"> <listbox x:name="mylistbox" borderthickness="1" width="200" height="200" borderbrush="#ce5e48" displaymemberpath="name" background="aliceblue" selectedindex="{binding path=datacontext.myselectedindex, mode=onewaytosource, elementname=maindatacontext}" /> <label name="selectedindex" verticalalignment="top" content="{binding myselectedindex}" contentstringformat="selectedindex: {0}" width="100" height="30" background="lavender" /> </grid> </contentcontrol>
as understand, not work.
datacontext
set on specific node of visual tree, items below (in visual tree) inherit it. means datacontext
working
since grid
, below visual tree. therefore, following code work:
<contentcontrol x:name="maindatacontext"> <grid x:name="maingrid" datacontext="{staticresource selectedindexclass}"> <listbox x:name="mylistbox" borderthickness="1" width="200" height="200" borderbrush="#ce5e48" displaymemberpath="name" background="aliceblue" selectedindex="{binding path=datacontext.myselectedindex, mode=onewaytosource, elementname=maingrid}" /> <label name="selectedindex" verticalalignment="top" content="{binding myselectedindex}" contentstringformat="selectedindex: {0}" width="100" height="30" background="lavender" /> </grid> </contentcontrol>
and also, work if name of point mylistbox
. usually, when set datacontext
, element name passed.
Comments
Post a Comment