c# - mvvm confusion with canexecute and binding commands -
i'm having hard time wrapping head around logic in tutorials , posts subject. i'm trying implement in wpf application i'm writing.
basically, i'm using listbox display tostring of objects in list , allowing users add , remove list , corresponding listbox via add , remove button. problem i'm having implementation of remove button. want button disabled if no listbox item selected, 1 of things pattern for. i'm lost how implement condition.
at moment, button not enabling when highlight listbox item. suppose canexecutechanged event isn't firing.. how need change this?
my commandshandler class:
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; using system.windows.input; namespace techopstools { public class commandhandler : icommand { private action<object> _execute; private bool _canexecute; public commandhandler(action<object> execute) : this(execute, true) { } public commandhandler(action<object> execute, bool canexecute) { if (execute == null) throw new argumentnullexception("execute"); _execute = execute; _canexecute = canexecute; } public bool canexecute(object parameter) { return _canexecute; } public void execute(object parameter) { _execute(parameter); } public event eventhandler canexecutechanged { add { commandmanager.requerysuggested += value; } remove { commandmanager.requerysuggested -= value; } } } }
my viewmodel:
using system; using system.collections.generic; using system.linq; using system.net; using system.text; using system.threading.tasks; using protobuf; using system.windows; using system.componentmodel; using system.collections.objectmodel; using system.windows.input; namespace techopstools { class logcheckclientviewmodel : inotifypropertychanged { private string uri; private string response; private bool _canremove; private logconstraints selectedconstraints; private observablecollection<logconstraints> constraints; public event propertychangedeventhandler propertychanged; public logconstraints selectedconstraints { { return selectedconstraints; } set { selectedconstraints = value; onpropertychanged("selectedconstraints"); } } private commandhandler removeitemcommand; public icommand removeitemcommand { { if (removeitemcommand == null) removeitemcommand = new commandhandler(param => removeconstraint(), selectedconstraints != null); return removeitemcommand; } } public string response { { return response; } set { response = value; onpropertychanged("response"); } } public string uri { { return uri; } set { uri = value; onpropertychanged("uri"); } } public observablecollection<logconstraints> constraints { { return constraints; } set { constraints = value; onpropertychanged("constraints"); } } public logcheckclientviewmodel() { constraints = new observablecollection<logconstraints>(); } public void addconstraint() { newconstraint newconstraint = new newconstraint(); newconstraint.showdialog(); if (newconstraint._vm.constraint != null) { constraints.add(newconstraint._vm.constraint); } } private void removeconstraint() { constraints.remove(selectedconstraints); onpropertychanged("constraints"); }
xaml:
<window x:class="techopstools.logcheckclient" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:techopstools" title="logcheck" height="453.057" width="495.986"> <grid> <textbox text="{binding response}" horizontalalignment="left" height="128" margin="38,212,0,0" textwrapping="wrap" verticalalignment="top" width="413" verticalscrollbarvisibility="auto" isenabled="false"/> <label content="response" horizontalalignment="left" margin="38,188,0,0" verticalalignment="top" width="78" height="24"/> <textbox text="{binding uri}" horizontalalignment="left" height="23" margin="38,26,0,0" textwrapping="wrap" verticalalignment="top" width="413"/> <label content="uri" horizontalalignment="left" margin="38,0,0,0" verticalalignment="top" width="78" height="24"/> <button content="add constraint" horizontalalignment="left" margin="38,54,0,0" verticalalignment="top" width="127" height="56" click="add_click"/> <button x:name="submit" content="submit request" horizontalalignment="left" margin="38,345,0,0" verticalalignment="top" width="413" height="70" click="submit_click"/> <listbox selecteditem="{binding path=selectedconstraints,updatesourcetrigger=propertychanged}" itemssource="{binding constraints}" horizontalalignment="left" height="124" margin="182,54,0,0" verticalalignment="top" width="269"> <listbox.itemtemplate> <datatemplate> <stackpanel orientation="horizontal"> <textblock text="{binding path=description}" /> </stackpanel> </datatemplate> </listbox.itemtemplate> </listbox> <button command="{binding removeitemcommand}" content="remove constraint" horizontalalignment="left" margin="38,122,0,0" verticalalignment="top" width="127" height="56" /> </grid> </window>
you need using canexecute
delegate same way you're doing execute
handler.
basically right checking if can execute when removeitemcommand
first accessed. keeps value entire time.
if pass in delegate same condition (perhaps adding in empty list, not null list), i'm betting it'll work.
in other words, in commandhandler, change
private bool _canexecute;
to
private func<bool,object> _canexecute;
and change
public bool canexecute(object parameter) { return _canexecute; }
to
public bool canexecute(object parameter) { return _canexecute(parameter); }
and in viewmodel, change
removeitemcommand = new commandhandler(param => removeconstraint(), selectedconstraints != null);
to
removeitemcommand = new commandhandler(param => removeconstraint(), param => selectedconstraints != null);
(note might not exactly right code, writing freehand, point)
Comments
Post a Comment