c# - WPF CheckedListBox SelectionMode="Multiple" not updating SelectedIndex on SelectionChanged Event -
i testing kelly elias' article on creating wpf checklistbox. i'm needing selectedindex , checkedbox text. works needed until change listbox's selectionmode "multiple" need implemented. after that, selectedindex nor selecteditem not change using selectionchanged event. these 2 properties show info of first checkedbox. however, of checkedboxes added selecteditems collection. can please assist issue?
thank in advance!!!
using system.collections.objectmodel; using system.componentmodel; using system.windows; using system.windows.controls; namespace jarloo { public class customer : inotifypropertychanged { private string _name; public string name { { return _name; } set { _name = value; notifypropertychanged("name"); } } public event propertychangedeventhandler propertychanged; protected void notifypropertychanged(string propertyname) { if (propertychanged != null) propertychanged(this, new propertychangedeventargs(propertyname)); } } public class checkedlistitem<t> : inotifypropertychanged { public event propertychangedeventhandler propertychanged; private bool ischecked; private t item; public checkedlistitem() { } public checkedlistitem(t item, bool ischecked = false) { this.item = item; this.ischecked = ischecked; } public t item { { return item; } set { item = value; if (propertychanged != null) propertychanged(this, new propertychangedeventargs("item")); } } public bool ischecked { { return ischecked; } set { ischecked = value; if (propertychanged != null) propertychanged(this, new propertychangedeventargs("ischecked")); } } } /// <summary> /// interaction logic mainwindow.xaml /// </summary> public partial class mainwindow : window { public observablecollection<checkedlistitem<customer>> customers { get; set; } public mainwindow() { initializecomponent(); customers = new observablecollection<checkedlistitem<customer>>(); customers.add(new checkedlistitem<customer>(new customer() { name = "kelly smith" })); customers.add(new checkedlistitem<customer>(new customer() { name = "joe brown" })); customers.add(new checkedlistitem<customer>(new customer() { name = "herb dean" })); customers.add(new checkedlistitem<customer>(new customer() { name = "john paul" })); datacontext = this; } private void listbox_selectionchanged(object sender, selectionchangedeventargs e) { int index = listbox1.selectedindex; string testname = ((checkedlistitem<customer>)listbox1.selectedvalue).item.name; } } } <window x:class="jarloo.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" height="350" width="525" windowstartuplocation="centerscreen"> <grid> <listbox name="listbox1" itemssource="{binding customers}" selectionchanged="listbox_selectionchanged" selectionmode="multiple"> <listbox.itemtemplate> <datatemplate> <checkbox ischecked="{binding relativesource={relativesource ancestortype={x:type listboxitem}}, path=isselected}" content="{binding path=item.name}"/> </datatemplate> </listbox.itemtemplate> </listbox> </grid> </window>
the way control works when selectionmode
multiple
(or extended
), set selectedindex
only when first item selected (i.e. added selecteditems
). additional items added end of selecteditems
list, selectedindex
remains unchanged.
to trick behavior desired results, take newly added item(s) off end of selecteditems
, insert it(them) front. work, have more make newest item first item in selecteditems
. have empty list , re-add each entry default behavior recognizes desired item selectedvalue
, update selectedindex
. we'll use temporary list help.
additionally, we'll add flag indicate if busy correcting selecteditems
order. needed since modifying list , listbox.selectionchanged
recursively called.
private bool busy; private void listbox_selectionchanged(object sender, selectionchangedeventargs e) { if (!this.busy) { this.busy = true; /* * if items added end of list, * reverse list appropriately. * removed items self-handling. */ if (e.addeditems.count > 0) { list<checkedlistitem<customer>> reversed = new list<checkedlistitem<customer>>(); // reverse newly added items. foreach (var item in e.addeditems) { listbox1.selecteditems.remove(item); reversed.insert(0, (checkedlistitem<customer>)item); } // maintain reversed items' orders. foreach (var item in listbox1.selecteditems) { reversed.add((checkedlistitem<customer>)item); } // clear , reset selections trigger selectedindex change. listbox1.unselectall(); foreach (var item in reversed) { listbox1.selecteditems.add(item); } } int index = listbox1.selectedindex; string testname = listbox1.selectedvalue == null ? string.empty : ((checkedlistitem<customer>)listbox1.selectedvalue).item.name; system.console.writeline("{0} {1}", index, testname); this.busy = false; } }
sidenote: instead of busy
flag , condition check, instead following:
private void listbox_selectionchanged(object sender, selectionchangedeventargs e) { listbox1.selectionchanged -= this.listbox_selectionchanged; // same code within condition... listbox1.selectionchanged += this.listbox_selectionchanged; }
it achieve same purpose of preventing recursive call , subsequent stack overflow. don't know whether unsubscribing , subscribing event handler less or more expensive boolean check (my guess more researching, there seems no preference, shown in these three results).
Comments
Post a Comment