WPF Data binding: CollectionViewSource and ObjectDataProvider issue -
i have mainwindow.xaml file:
<window.resources> <collectionviewsource x:key="cvs" source="{binding source={staticresource resourcekey=detailscollection}}" /> <collectionviewsource x:key="detailscopes"> <collectionviewsource.source> <objectdataprovider methodname="getvalues" objecttype="{x:type system:enum}"> <objectdataprovider.methodparameters> <x:type typename="entities:detailscope" /> </objectdataprovider.methodparameters> </objectdataprovider> </collectionviewsource.source> </collectionviewsource> <datatemplate x:key="accountdetail" datatype="{x:type entities:accountdetail}"> <dockpanel> <combobox dockpanel.dock="left" itemssource="{binding source={staticresource resourcekey=detailscopes}}" selecteditem="{binding path=scope}"> <combobox.itemtemplate> <datatemplate> <textblock text="{binding converter={staticresource detailscopeconverter}}" /> </datatemplate> </combobox.itemtemplate> </combobox> <textbox text="{binding path=value}" /> </dockpanel> </datatemplate> </window.resources> ... <listbox itemtemplate="{staticresource resourcekey=accountdetail}" itemssource="{binding source={staticresource resourcekey=cvs}}" />
and code-behind class, defined filter detail scopes:
public class mainwindow { public mainwindow() { collectionviewsource detailscopes; initializecomponent(); // attach filter collection view source detailscopes = this.resources["detailscopes"] collectionviewsource; detailscopes.filter += new filtereventhandler(detailscopesfilter); private void detailscopesfilter(object sender, filtereventargs e) { detailscope scope; scope = (detailscope)e.item; if (scope == detailscope.private || scope == detailscope.business) { e.accepted = true; } else { e.accepted = false; } } } }
next, there's accountdetail
class:
public class accountdetail { public string value { { return this.value; } set { this.value = value; } } public detailscope scope { { return scope; } set { scope = value; } } private string value; private detailscope scope; }
finally, enum:
public enum detailscope { private, business, other }
when run code, list box populated bunch of account details, each having own combo box selected scope , text box appropriate value. problem selected values in combo boxes match scope set last entered detail , changing of combo box values updates of them, if bound same account detail.
when take out objectdataprovider
collectionviewsource
detailscopes , bind directly combo box's itemssource
in datatemplate
accountdetail, problem gone. however, need inside collectionviewsource
because applying filtering , cannot apply filtering objectdataprovider
.
could please explain why happening , how supposed connect collectionviewsource
, objectdataprovider
? thank you.
.
the problem code every combobox using same instance of collectionviewsource; means, resource key "detailscopes" shared all combobox, whenever select 1 value particular combobox, automatically selects same value in combobox. it's because underlying collection shared, keeps track of selected item, , since changes on selecting 1 combobox, collectionviewsource notifies change combobox.
so solution simple. need make detailscopes resource unsharable.
here fix:
<!-- please note x:shared="false" after x:key="detailsscopes" ---> <collectionviewsource x:key="detailscopes" x:shared="false"> <collectionviewsource.source> <objectdataprovider methodname="getvalues" objecttype="{x:type system:enum}"> <objectdataprovider.methodparameters> <x:type typename="entities:detailscope" /> </objectdataprovider.methodparameters> </objectdataprovider> </collectionviewsource.source> </collectionviewsource>
hope solves problem!
however, solution cause problem. let me quote msdn, you'll understand x:shared does.
x:shared attribute
when set false, modifies wpf resource-retrieval behavior requests attributed resource create new instance each request instead of sharing same instance requests.
since x:shared causes create new instance (a new copy) of resource whenever attempt access it, means, filter handler method attached instance in code-behind, not instances.
so in order work handler properly, need attach handler xaml itself, this:
<!-- please note filter="detailsscopesfilter" ---> <collectionviewsource x:key="detailscopes" x:shared="false" filter="detailscopesfilter"> <collectionviewsource.source> <objectdataprovider methodname="getvalues" objecttype="{x:type system:enum}"> <objectdataprovider.methodparameters> <x:type typename="entities:detailscope" /> </objectdataprovider.methodparameters> </objectdataprovider> </collectionviewsource.source> </collectionviewsource>
hope solves problems. let me know if still face any.:-)
oh way, following code-behind not needed anymore. please remove it.
// attach filter collection view source detailscopes = this.resources["detailscopes"] collectionviewsource; detailscopes.filter += new filtereventhandler(detailscopesfilter);
.
Comments
Post a Comment