wpf - how to refresh multi binding -
in listbox have items checkboxes , in textblock want update counter showing how many of them checked. simple scenario, have problems refreshing binding counter.
my xaml:
<window x:class="listboxwithcounting.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:listboxwithcounting" title="mainwindow" height="350" width="525"> <window.datacontext> <vm:myviewmodel /> </window.datacontext> <window.resources> <datatemplate x:key="checkboxlistitem"> <border x:name="checkboxitemelement" background="transparent" padding="0,2,0,2"> <checkbox content="{binding name}" ischecked="{binding path=ischecked,mode=twoway, updatesourcetrigger=propertychanged}"/> </border> </datatemplate> </window.resources> <grid> <grid.columndefinitions> <columndefinition width="*" /> <columndefinition width="*"/> </grid.columndefinitions> <grid.rowdefinitions> <rowdefinition height="*" /> </grid.rowdefinitions> <textblock grid.column="1"> <textblock.text> <multibinding stringformat="items checked: {0} of {1}"> <binding path="columnschecked" /> <binding path="columnscount" /> </multibinding> </textblock.text> </textblock> <listbox itemtemplate="{staticresource checkboxlistitem}" x:name="columns" itemssource="{binding columns}" /> </grid> </window>
my view model , single item:
public class item : inotifypropertychanged { public string name { set; get; } private bool ischecked; public bool ischecked { { return ischecked; } set { ischecked = value; propertychanged(this, new propertychangedeventargs("ischecked")); } } public event propertychangedeventhandler propertychanged = delegate { }; } public class myviewmodel { public int columnscount { { return columns.count; } } public int columnschecked { { return columns.where(x => x.ischecked).count(); } } public list<item> columns { { var data = new list<item>() { new item(){ name = "item1", ischecked=true }, new item(){ name = "item2" }, new item(){ name = "item3" } }; data.foreach(x => x.propertychanged += (s, e) => { }); return data; } } }
how can trigger multibinding when each , every checkbox on list state changed?
[update]
thanks slugster, working code:
public class item : inotifypropertychanged { public string name { set; get; } private bool ischecked; public bool ischecked { { return ischecked; } set { if (ischecked != value) { ischecked = value; propertychanged(this, new propertychangedeventargs("ischecked")); } } } public event propertychangedeventhandler propertychanged = delegate { }; } public class myviewmodel : inotifypropertychanged { public int columnscount { { return columns.count; } } public int columnschecked { { return columns.where(x => x.ischecked).count(); } } private list<item> columns; public list<item> columns { { if (columns == null) { columns = new list<item>() { new item(){ name = "item1", ischecked=true }, new item(){ name = "item2" }, new item(){ name = "item3" } }; } columns.foreach(x => { x.propertychanged -= x_propertychanged; x.propertychanged += x_propertychanged; }); return columns; } } void x_propertychanged(object sender, propertychangedeventargs e) { propertychanged(this, new propertychangedeventargs("columnschecked")); } public event propertychangedeventhandler propertychanged = delegate { }; }
your viewmodel needs implement inotifypropertychanged
binding can made aware of property change on list items.
to honest can't tell off top of head whether notifying on 1 property cause whole multibinding evaluated (in case can find out), want notify on both properties in case of other bindings.
public class myviewmodel : inotifypropertychanged { [...snip...] public list<item> columns { { var data = new list<item>() { new item(){ name = "item1", ischecked=true }, new item(){ name = "item2" }, new item(){ name = "item3" } }; data.foreach(x => x.propertychanged += (s, e) => { onpropertychanged("columnscount"); onpropertychanged("columnschecked"); }); return data; } } private void onpropertychanged(string propertyname) { var handler = propertychanged; if (handler != null) handler(this, new propertychangedeventargs(propertyname)); } public event propertychangedeventhandler propertychanged; }
Comments
Post a Comment