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 original datacontext (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

Popular posts from this blog

qt - Using float or double for own QML classes -

Create Outlook appointment via C# .Net -

ios - Swift Array Resetting Itself -