c# - Binding SelectedItems of ListView to ViewModel -


i have list view binding items property in viewmodel.

<listview height="238"            horizontalalignment="left"            name="listview"            verticalalignment="top"            width="503"           itemssource="{binding businesscollection}"           selectionmode="multiple"           >     <listview.view>         <gridview>             <gridview.columns>                 <gridviewcolumn>                     <gridviewcolumn.celltemplate>                         <datatemplate>                            <checkbox  ischecked="{binding relativesource={relativesource ancestortype={x:type listviewitem}}, path=isselected}" />                          </datatemplate>                     </gridviewcolumn.celltemplate>                 </gridviewcolumn>                 <gridviewcolumn displaymemberbinding="{binding id}" header="id" />                 <gridviewcolumn displaymemberbinding="{binding name}" header="name" />             </gridview.columns>         </gridview>     </listview.view> </listview> 

and in viewmodel.

icollectionview _businesscollection public icollectionview businesscollection { {return _businesscollection;} set{ _businesscollection=value; raisepropertyonchange("businesscollection"); } } 

how selected item of businesscollection in viewmodel?

1. 1 way source binding:

you have use selectionchanged event. easiest way write eventhandler in codebehind "bind selecteditems" viewmodel.

//viewmodel public icollectionview businesscollection {get; set;} public list<yourbusinessitem> selectedobject {get; set;}  //codebehind private void listview_selectionchanged(object sender, selectionchangedeventargs e) {     var viewmodel = (viewmodel) datacontext;     viewmodel.selecteditems = listview.selecteditems         .cast<yourbusinessitem>()         .tolist(); } 

this still aligns mvvm design, because view , viewmodel resposibilities kept separated. dont have logic in codebehind , viewmodel clean , testable.

2. 2 way binding:

if need update view, when viewmodel changes, have attach viewmodel's propertychanged event , selected items' collectionchanged event. of course can in codebehind, in case create more reusable:

//viewmodel public observablecollection<yourbusinessitem> selectedobject {get; set;}  //in codebehind: var binder = new selecteditemsbinder(listview, viewmodel.selecteditems); binder.bind(); 

or can create custom attached property, can use binding syntax in xaml:

<listview local:listviewextensions.selectedvalues="{binding selecteditem}" .../> 
public class selecteditemsbinder {     private listview _listbox;     private ilist _collection;       public selecteditemsbinder(listview listbox, ilist collection)     {         _listbox = listbox;         _collection = collection;          _listbox.selecteditems.clear();          foreach (var item in _collection)         {             _listbox.selecteditems.add(item);         }     }      public void bind()     {         _listbox.selectionchanged += listbox_selectionchanged;          if (_collection inotifycollectionchanged)         {             var observable = (inotifycollectionchanged) _collection;             observable.collectionchanged += collection_collectionchanged;         }     }      public void unbind()     {         if (_listbox != null)             _listbox.selectionchanged -= listbox_selectionchanged;          if (_collection != null && _collection inotifycollectionchanged)         {             var observable = (inotifycollectionchanged) _collection;             observable.collectionchanged -= collection_collectionchanged;         }     }      private void collection_collectionchanged(object sender, notifycollectionchangedeventargs e)     {         foreach (var item in e.newitems ?? new object[0])         {             if (!_listbox.selecteditems.contains(item))                 _listbox.selecteditems.add(item);         }         foreach (var item in e.olditems ?? new object[0])         {             _listbox.selecteditems.remove(item);         }     }      private void listbox_selectionchanged(object sender, selectionchangedeventargs e)     {         foreach (var item in e.addeditems ?? new object[0])         {             if (!_collection.contains(item))                 _collection.add(item);         }          foreach (var item in e.removeditems ?? new object[0])         {             _collection.remove(item);         }     } } 

attached property implementation

public class listboxextensions {      private static selecteditemsbinder getselectedvaluebinder(dependencyobject obj)     {         return (selecteditemsbinder)obj.getvalue(selectedvaluebinderproperty);     }      private static void setselectedvaluebinder(dependencyobject obj, selecteditemsbinder items)     {         obj.setvalue(selectedvaluebinderproperty, items);     }      private static readonly dependencyproperty selectedvaluebinderproperty = dependencyproperty.registerattached("selectedvaluebinder", typeof(selecteditemsbinder), typeof(listboxextensions));       public static readonly dependencyproperty selectedvaluesproperty = dependencyproperty.registerattached("selectedvalues", typeof(ilist), typeof(listboxextensions),         new frameworkpropertymetadata(null, onselectedvalueschanged));       private static void onselectedvalueschanged(dependencyobject o, dependencypropertychangedeventargs value)     {         var oldbinder = getselectedvaluebinder(o);         if (oldbinder != null)             oldbinder.unbind();          setselectedvaluebinder(o, new selecteditemsbinder((listbox)o, (ilist)value.newvalue));         getselectedvaluebinder(o).bind();     }      public static void setselectedvalues(selector elementname, ienumerable value)     {         elementname.setvalue(selectedvaluesproperty, value);     }      public static ienumerable getselectedvalues(selector elementname)     {         return (ienumerable)elementname.getvalue(selectedvaluesproperty);     } } 

Comments

Popular posts from this blog

Android : Making Listview full screen -

javascript - Parse JSON from the body of the POST -

javascript - Chrome Extension: Interacting with iframe embedded within popup -