c# - Treeview IsExpanded not fires up -
i trying add treeview
ability catch isexpanded
event. when item expand raise property or command on view model.
here code:
<treeview name="scenariostreeview" itemssource="{binding path=cat, mode=twoway}" focusable="true" > <treeview.inputbindings> <keybinding key="delete" command="{binding deletecommand}" commandparameter="{binding selectedvalue ,elementname=scenariostreeview}" /> </treeview.inputbindings> <treeview.itemcontainerstyle> <style targettype="{x:type treeviewitem}"> <setter property="isexpanded" value="{binding isextended, mode=twoway}" /> <setter property="isselected" value="{binding isselected, mode=twoway}"/> </style> </treeview.itemcontainerstyle> <treeview.resources> <hierarchicaldatatemplate datatype="{x:type sotc:scenariocategory}" itemssource="{binding path=scenariolist}" > <textblock text="{binding path=name}" foreground="black" isenabled="true" focusable="true"/> </hierarchicaldatatemplate> <datatemplate datatype="{x:type sotc:scenario}" > <textblock text="{binding path=name, mode=twoway}" /> </datatemplate> </treeview.resources> </treeview>
i have property in viewmodel isexpanded
(and isselected) , none of raises when expand treeviewitem
. ideas?
thanks ahead,
tried reproduce issue , implemented attached behavior calling command when node expanded , works fine. complete code solution:
xaml
<window x:class="treeviewtest.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:sotc="clr-namespace:treeviewtest" mc:ignorable="d" title="mainwindow" height="350" width="525"> <window.datacontext> <sotc:mainwindowviewmodel /> </window.datacontext> <grid> <treeview name="scenariostreeview" itemssource="{binding path=cat, mode=twoway}" focusable="true" > <treeview.inputbindings> <keybinding key="delete" command="{binding deletecommand}" commandparameter="{binding selectedvalue ,elementname=scenariostreeview}" /> </treeview.inputbindings> <treeview.itemcontainerstyle> <style targettype="{x:type treeviewitem}"> <setter property="isexpanded" value="{binding isextended, mode=twoway}" /> <setter property="isselected" value="{binding isselected, mode=twoway}"/> <setter property="sotc:behaviours.expandingbehaviour" value="{binding datacontext.expandingcommand, relativesource={relativesource ancestortype=window}}"/> </style> </treeview.itemcontainerstyle> <treeview.resources> <hierarchicaldatatemplate datatype="{x:type sotc:scenariocategory}" itemssource="{binding path=scenariolist}" > <textblock text="{binding path=name}" foreground="black" isenabled="true" focusable="true"/> </hierarchicaldatatemplate> <datatemplate datatype="{x:type sotc:scenario}" > <textblock text="{binding path=name, mode=twoway}" /> </datatemplate> </treeview.resources> </treeview> </grid> </window>
c#
public class viewmodelbase : inotifypropertychanged { public void onpropertychanged([callermembername] string name = null) { propertychanged?.invoke(this, new propertychangedeventargs(name)); } public event propertychangedeventhandler propertychanged; } public class mainwindowviewmodel : viewmodelbase { public icommand expandingcommand { get; set; } private void executeexpandingcommand(object obj) { console.writeline(@"expanded"); } private bool canexecuteexpandingcommand(object obj) { return true; } public mainwindowviewmodel() { expandingcommand = new relaycommand(executeexpandingcommand, canexecuteexpandingcommand); cat = new observablecollection<scenariocategory>(new scenariocategory[] { new scenariocategory { name = "c1" }, new scenariocategory { name = "c2" }, new scenariocategory { name = "c3" } }); } public observablecollection<scenariocategory> cat { get; set; } } public class scenariocategory : viewmodelbase { string _name; public string name { { return _name; } set { _name = value; onpropertychanged(); } } bool _isextended; public bool isextended { { return _isextended; } set { _isextended = value; console.writeline(@"isextended set"); onpropertychanged(); } } bool _isselected; public bool isselected { { return _isselected; } set { _isselected = value; console.writeline(@"isselected set"); onpropertychanged(); } } public observablecollection<scenario> scenariolist { get; set; } public scenariocategory() { scenariolist = new observablecollection<scenario>(new scenario[] { new scenario { name = "1" }, new scenario { name = "2" }, new scenario { name = "3" } }); } } public class scenario : viewmodelbase { string _name; public string name { { return _name; } set { _name = value; onpropertychanged(); } } bool _isextended; public bool isextended { { return _isextended; } set { _isextended = value; onpropertychanged(); } } bool _isselected; public bool isselected { { return _isselected; } set { _isselected = value; onpropertychanged(); } } } public static class behaviours { public static readonly dependencyproperty expandingbehaviourproperty = dependencyproperty.registerattached("expandingbehaviour", typeof(icommand), typeof(behaviours), new propertymetadata(onexpandingbehaviourchanged)); public static void setexpandingbehaviour(dependencyobject o, icommand value) { o.setvalue(expandingbehaviourproperty, value); } public static icommand getexpandingbehaviour(dependencyobject o) { return (icommand)o.getvalue(expandingbehaviourproperty); } private static void onexpandingbehaviourchanged(dependencyobject d, dependencypropertychangedeventargs e) { treeviewitem tvi = d treeviewitem; if (tvi != null) { icommand ic = e.newvalue icommand; if (ic != null) { tvi.expanded += (s, a) => { if (ic.canexecute(a)) { ic.execute(a); } a.handled = true; }; } } } } public class relaycommand : icommand { private action<object> execute; private func<object, bool> canexecute; public event eventhandler canexecutechanged { add { commandmanager.requerysuggested += value; } remove { commandmanager.requerysuggested -= value; } } public relaycommand(action<object> execute, func<object, bool> canexecute = null) { this.execute = execute; this.canexecute = canexecute; } public bool canexecute(object parameter) { return this.canexecute == null || this.canexecute(parameter); } public void execute(object parameter) { this.execute(parameter); } }
Comments
Post a Comment