Thursday, 15 August 2013

c# - WPF Attached behavior error | Items collection must be empty before using ItemsSource -



c# - WPF Attached behavior error | Items collection must be empty before using ItemsSource -

i'm trying write mutli select treeview behavior, while doing i'm getting cryptic error "items collection must empty before using itemssource."

the next xaml code:

<window x:class="treeview.spike.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:spike="clr-namespace:treeview.spike" title="mainwindow" height="350" width="525"> <window.resources> </window.resources> <grid> <grid.columndefinitions> <columndefinition width=".5*"/> <columndefinition width=".5*"/> </grid.columndefinitions> <grid.rowdefinitions> <rowdefinition height="*"></rowdefinition> <rowdefinition height="40"></rowdefinition> </grid.rowdefinitions> <treeview itemssource="{binding nodes}" grid.row="0" x:name="treeview" grid.column="0"> <treeview.itemtemplate> <hierarchicaldatatemplate itemssource="{binding nodes}"> <stackpanel orientation="horizontal"> <textblock text="{binding name}"> </textblock> </stackpanel> </hierarchicaldatatemplate> </treeview.itemtemplate> <treeview.contextmenu> <contextmenu> <menuitem header="add"></menuitem> <menuitem header="delete"></menuitem> </contextmenu> </treeview.contextmenu> <spike:multipleitemselectionattachedbehavior allselecteditems="{binding path=allselectednodes}"/> </treeview> </grid> </window>

my attached behavior:

public class multipleitemselectionattachedbehavior:behavior<system.windows.controls.treeview> { public static dependencyproperty allselecteditemsproperty = dependencyproperty.registerattached("allselecteditems", typeof(object), typeof(multipleitemselectionattachedbehavior), new frameworkpropertymetadata(null, frameworkpropertymetadataoptions.bindstwowaybydefault | frameworkpropertymetadataoptions.inherits)); private static readonly propertyinfo isselectionchangeactiveproperty = typeof(system.windows.controls.treeview).getproperty("isselectionchangeactive", bindingflags.nonpublic | bindingflags.instance); public object allselecteditems { { homecoming (object)getvalue(allselecteditemsproperty); } set { setvalue(allselecteditemsproperty, value); } } public static bool getallselecteditems(dependencyobject obj) { homecoming (bool)obj.getvalue(allselecteditemsproperty); } public static void setallselecteditems(dependencyobject obj, bool value) { obj.setvalue(allselecteditemsproperty, value); } protected override void onattached() { base.onattached(); associatedobject.selecteditemchanged += associatedobject_selecteditemchanged; } protected override void ondetaching() { base.ondetaching(); associatedobject.selecteditemchanged -= associatedobject_selecteditemchanged; } void associatedobject_selecteditemchanged(object sender, routedpropertychangedeventargs<object> e) { if (isselectionchangeactiveproperty == null) return; var selecteditems = new list<node>(); var treeviewitem = associatedobject.selecteditem node; if (treeviewitem == null) return; // allow multiple selection // when command key pressed if (keyboard.iskeydown(key.leftctrl) || keyboard.iskeydown(key.rightctrl)) { var isselectionchangeactive = isselectionchangeactiveproperty.getvalue(associatedobject, null); isselectionchangeactiveproperty.setvalue(associatedobject, true, null); selecteditems.foreach(item => item.isselected = true); isselectionchangeactiveproperty.setvalue(associatedobject, isselectionchangeactive, null); } else { // deselect selected items except current 1 selecteditems.foreach(item => item.isselected = (item == treeviewitem)); selecteditems.clear(); } if (!selecteditems.contains(treeviewitem)) { selecteditems.add(treeviewitem); } else { // deselect if selected treeviewitem.isselected = false; selecteditems.remove(treeviewitem); } allselecteditems = selecteditems; } }

..and viewmodel

public class viewmodel :notificationobject { public viewmodel() { allselectednodes = new observablecollection<node>(); } private observablecollection<node> _allselectednodes; public observablecollection<node> allselectednodes { { homecoming _allselectednodes; } set { _allselectednodes = value; raisepropertychanged(() => allselectednodes); } } }

my model:

public class node:notificationobject { private string _name; public string name { { homecoming _name; } set { _name = value; raisepropertychanged(() => name); } } private bool _isexpanded = true; public bool isexpanded { { homecoming _isexpanded; } set { _isexpanded = value; raisepropertychanged(() => isexpanded); } } private bool _isselected; public bool isselected { { homecoming _isselected; } set { _isselected = value; raisepropertychanged(() => isselected); } } private observablecollection<node> _nodes; public observablecollection<node> nodes { { homecoming _nodes; } set { _nodes = value; raisepropertychanged(() => nodes); } } public static ilist<node> create() { homecoming new list<node>() { new node() { name = "activity", nodes = new observablecollection<node>() { new node() {name = "company",nodes = new observablecollection<node>(){ new node() {name = "company1",existing = false}}}, new node() {name = "strategy",nodes = new observablecollection<node>(){ new node() {name = "strategy1"}}}, new node() {name = "vehicle",nodes = new observablecollection<node>(){ new node() {name = "vehicle1",existing = false}}} } } }; } }

..and initialization clode:

public partial class mainwindow : window { public mainwindow() { initializecomponent(); var viewmodel = new viewmodel(); this.datacontext = viewmodel; viewmodel.nodes = new observablecollection<node>(node.create()); } }

i have no clue going wrong here, please help?

you're missing <i:interaction.behaviors> element:

replace:

<spike:multipleitemselectionattachedbehavior allselecteditems="{binding path=allselectednodes}"/>

for:

<i:interaction.behaviors> <spike:multipleitemselectionattachedbehavior allselecteditems="{binding path=allselectednodes}"/> </i:interaction.behaviors>

the problem default content property treeview items property, hence putting xaml element of behavior within of treeview element without specifying <i:interaction.behaviors> attached property, telling wpf want behavior item in treeview, hence when trying set itemssource property recieve error, because there item within of it.

c# wpf

No comments:

Post a Comment