mvvm - Binding from within a ResourceDictionary in a Catel WPF UserControl -
i converting of views , view models of our wpf application on catel, proof-of-concept.
one of user controls doesn't seem correctly binding view model @ runtime. think understand why is, feedback on best remedy is.
the code
i have simple view model observablecollection
:
persontable.xaml
key things note: i'm using collectionviewsource
wraps main collection datagrid
binds to. can keep grid auto-sorted.
<catel:usercontrol x:class="myapp.persontable" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:scm="clr-namespace:system.componentmodel;assembly=windowsbase" xmlns:catel="http://catel.codeplex.com" mc:ignorable="d" d:designheight="300" d:designwidth="200" d:datacontext="{dynamicresource designtimeviewmodel}"> <usercontrol.resources> <resourcedictionary> <collectionviewsource source="{binding personitems}" x:key="personitemssource"> <collectionviewsource.sortdescriptions> <scm:sortdescription propertyname="dob" direction="descending" /> </collectionviewsource.sortdescriptions> </collectionviewsource> <ui:designpersonviewmodel x:key="designtimeviewmodel" /> </resourcedictionary> </usercontrol.resources> <grid> <datagrid itemssource="{binding source={staticresource personitemssource}}" autogeneratecolumns="false"> <datagrid.columns> <datagridtextcolumn binding="{binding name, mode=twoway}" header="name" width="90" elementstyle="{staticresource cellrightalign}" /> <!-- etc..... --> </datagrid.columns> </datagrid> </grid> </catel:usercontrol>
persontableviewmodel.cs
the view model accepts model in constructor:
using catel.mvvm; public class persontableviewmodel : viewmodelbase { public persontableviewmodel(observablecollection<person> personitems) { this.personitems = personitems } public observablecollection<person> personitems { { return getvalue<observablecollection<person>>(personitemsproperty); } set { setvalue(personitemsproperty, value); } } public static propertydata personitemsproperty = registerproperty("personitems", typeof(observablecollection<person>), () => new observablecollection<personitems>()); }
the problem
at runtime, no items populated in grid. although @ design time, design view model correctly populate grid in design view.
am right source of problem? believe it's control bound personitems
property not part of visual tree, embedded in control-level resource dictionary? based on reading of documentation, article usercontrol - under hood, seems catel usercontrol
class injects view model hidden inner datacontext
inside visual tree only, {binding}
inside resource dictionary item might left out in cold.
assuming i'm right, what's best remedy?
if i'm right above, can think of few possible remedies, none of seem perfect. love know accepted best practice remedy situation.
- move
collectionviewsource
code behind; expose dependency property. don't love option because can't configure in xaml. - move
collectionviewsource
view model. really don't love one; putting wpf components in view model breaks mvvm. bind
collectionviewsource
originaldatacontext
(i.e. model). problem there design-time view model not bind correctly.<collectionviewsource source="{binding}" ..... >
expose dependency property code-behind bound view model. update: works @ runtime, fails @ design time (in grid not contain test data.)
---- persontable.xaml.cs ---- [viewtoviewmodel(mappingtype = viewtoviewmodelmappingtype.viewmodeltoview] public observablecollection<personitem> personitems { { ... } } ---- persontable.xaml ---- <collectionviewsource source="{binding relativesource={relativesource findancestor, ancestortype={x:type persontable}}, path=personitems}" ...... >
your assumptions correct. there 4th remedy. put resources inside grid inside viewmodel data context:
<catel:usercontrol x:class="myapp.persontable" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:scm="clr-namespace:system.componentmodel;assembly=windowsbase" xmlns:catel="http://catel.codeplex.com" mc:ignorable="d" d:designheight="300" d:designwidth="200" d:datacontext="{dynamicresource designtimeviewmodel}"> <grid> <grid.resources> <resourcedictionary> <collectionviewsource source="{binding personitems}" x:key="personitemssource"> <collectionviewsource.sortdescriptions> <scm:sortdescription propertyname="dob" direction="descending" /> </collectionviewsource.sortdescriptions> </collectionviewsource> <ui:designpersonviewmodel x:key="designtimeviewmodel" /> </resourcedictionary> </grid.resources> <datagrid itemssource="{binding source={staticresource personitemssource}}" autogeneratecolumns="false"> <datagrid.columns> <datagridtextcolumn binding="{binding name, mode=twoway}" header="name" width="90" elementstyle="{staticresource cellrightalign}" /> <!-- etc..... --> </datagrid.columns> </datagrid> </grid> </catel:usercontrol>
Comments
Post a Comment