c# - WPF - MVVM : How to Check/Uncheck all Items in a ListView -
i have following requirements:
- window show
listview
multiple items. - user should able check (checkbox) item. a) if 1 item, items should unchecked , disabled. b) if checked item unchecked, items should enabled.
as of now, have following incomplete code.
mainwindow xaml:
<window x:class="wpfapplication4.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" height="520.149" width="732.463"> <window.resources> <resourcedictionary source="mainwindowresource.xaml" /> </window.resources> <grid> <listview x:name="mylistbox" itemtemplate="{staticresource offeringtemplate}"> <listview.itemspanel> <itemspaneltemplate> <uniformgrid columns="3" verticalalignment="top"/> </itemspaneltemplate> </listview.itemspanel> </listview> </grid> </window>
datatemplete listview:
<datatemplate x:key="offeringtemplate"> <stackpanel> <grid isenabled="{binding isenabled}"> <grid.columndefinitions> <columndefinition width="8"></columndefinition> <columndefinition width="120"></columndefinition> </grid.columndefinitions> <grid.rowdefinitions> <rowdefinition height="40"></rowdefinition> <rowdefinition height="50"></rowdefinition> <rowdefinition height="30"></rowdefinition> </grid.rowdefinitions> <rectangle grid.column="0" grid.rowspan="3" fill="#f4ca16" /> <label grid.column="1" grid.row="0" content="{binding title}" fontsize="18" fontweight="bold" margin="0,0,0,0" /> <textblock grid.column="1" grid.row="1" fontsize="10" text="{binding description}" foreground="black" textwrapping="wrapwithoverflow" margin="5,0,0,0" /> <checkbox grid.column="1" grid.row="2" fontsize="14" ischecked="{binding isselected}" verticalalignment="bottom" margin="5,0,0,0"> <textblock text="select" margin="0,-2,0,0"/> </checkbox> </grid> </stackpanel> </datatemplate>
model:
class mymodel { public string title { get; set; } public string description { get; set; } public bool isselected { get; set; } public bool isenabled { get; set; } }
viewmodel:
class myviewmodel : inotifypropertychanged { private mymodel offering; public myviewmodel() { offering = new mymodel(); } public int id { get; set; } public string title { { return offering.title; } set { offering.title = value; raisepropertychanged("title"); } } public string description { { return offering.description; } set { offering.description = value; raisepropertychanged("description"); } } public bool isselected { { return offering.isselected; } set { offering.isselected = value; raisepropertychanged("isselected"); } } public bool isenabled { { return offering.isenabled; } set { offering.isenabled = value; raisepropertychanged("isenabled"); } } public event propertychangedeventhandler propertychanged; private void raisepropertychanged(string propertyname) { var handler = propertychanged; if (handler != null) { handler(this, new propertychangedeventargs(propertyname)); } } }
this interesting question. since action want applies items in list, logic should in list class level. myviewmodel class fine. need add logic in list class , xaml prism, quite easy.
the list class (not shown in post) contains:
public observablecollection<myviewmodel> myitems { get; set; } //binding itemssource private icommand _selectcommand; public icommand selectcommand { { return _selectcommand ?? (_selectcommand = new delegatecommand<myviewmodel>(doselect)); } } private void doselect(myviewmodel myviewmodel) { foreach(var item in myitems) if (item != myviewmodel) { item.isselected = false; item.isenabled = false; } } private icommand _unselectcommand; public icommand unselectcommand { { return _unselectcommand ?? (_unselectcommand = new delegatecommand<myviewmodel>(dounselect)); } } private void dounselect(myviewmodel myviewmodel) { foreach (var item in myitems) if (item != myviewmodel) { item.isenabled = true; } }
there 2 commands, 1 selecting , other unselecting. magic on xaml:
<listview itemssource="{binding path=myitems}" x:name="listview"> <listview.itemtemplate> <datatemplate> <checkbox ischecked="{binding path=isselected}" isenabled="{binding path=isenabled}"> <i:interaction.triggers> <i:eventtrigger eventname="checked"> <i:invokecommandaction command="{binding elementname=listview, path=datacontext.selectcommand}" commandparameter="{binding}"/> </i:eventtrigger> <i:eventtrigger eventname="unchecked"> <i:invokecommandaction command="{binding elementname=listview, path=datacontext.unselectcommand}" commandparameter="{binding}"/> </i:eventtrigger> </i:interaction.triggers> </checkbox> </datatemplate> </listview.itemtemplate> </listview>
using prism's triggers, can map checkbox's checked , unchecked event list view model's commands , passing item view model parameter.
it working 1 thing annoying, setting item's isselected separate. when check checkbox, item behind set true through databinding others set through parent view model. if post requirement, can remove ischecked binding , put logic of setting 1 isselected inside list view model, looks clenaer , easier write test code.
Comments
Post a Comment