locked
DataTemplateSelector criterion versus DataTemplate DataContext RRS feed

  • Question

  •  

    This may apply to other places were a DataTemplateSelector is used, but my current problem is with a ContentControl's ContentTemplateSelector.

     

    In my ContentControl I specify a ContentTemplateSelector... which is a DataTemplateSelector..

    Note: I haven't been able to find detailed enough documentation and/or examples for my needs, so what I've learned is through experimentation.

    It looks to me like the DataTemplateSelector's SelectTemplate method's first parameter, which is an object, comes from whatever I bind the ContentControl's Content property to.

    So whatever I bind Content to should be the criterion that I use to choose my DataTemplate in the SelectTemplate method.

    But... it also looks like the DataContext of the DataTemplate I choose will ALSO be whatever I bind Content to!

    For me, this is a problem...

    Say I have an object called MyBusinessObject.  It has a property MyObjectTypeID.  Based on MyObjectTypeID, I want to choose a specific DataTemplate.  So I bind my ContentControl's Content to this property.  Now I am choosing the correct DataTemplate in SelectTemplate.

    But the DataContent of my chosen DataTemplate is also going to be MyObjectTypeID.  That's no good.  I need the entire MyBusinessObject!

     

    My workaround (which may seem obvious) is to bind the ContentControl's Content to MyBusinessObject.  Then within SelectTemplate I can simply access the MyObjectTypeID property within MyBusinessObject and make my DataTemplate choice.  And now, since Content is binded to MyBusinessObject, this will be the selected DataTemplate's DataContext, and I'm all set.  But wait...

     

    If I bind Content to MyBusinessObject, and only the MyObjectTypeID property within it gets changed (by some code and/or binding somewhere)... the ContentControl's Content will not know of this change and won't re-evaluate its ContentTemplateSelector. It will only reevaluate when the entire MyBusinessObject object changes.  Content really needs to be bound to MyObjectTypeID... but as described above, it really needs to be bound to MyBusinessObject!

     

    So I used MultiBinding and binded Content to both.  I bind to MyBusinessObject.MyObjectTypeID so there will be evaluation when this property changes, and I bind to MyBusinessObject so this object will be available as my DataTemplate's DataContext.  With Multibinding I need a converter.  And in this case, all it need to do is to return the MyBusinessObject that was passed into it, and ignore the MyObjectTypeID.  Now Content's value is MyBusinessObject and the ContentTemplateSelector's SelectTemplate method uses it to check the MyObjectTypeID property and choose a template.  And since Content is MyBusinessObject, the chosen DataTemplate with have this as it's DataContext.

     

    Yay!  (sort of)

    There is more of a problem that I bring up here:

    http://forums.microsoft.com/msdn/showpost.aspx?postid=1739625&siteid=1

     

    So I guess my question is... am I missing some way to tell the ContentControl: "this is what to use as the criterion for choosing a DataTemplate with ContentTemplateSelector"... and "this is the DataContext to use for chosen DataTemplate".

    If I could specify both of these, I think I'd be better off.

     

    Answers/Comments?

    Buzz

     

     

     

    Friday, June 15, 2007 3:50 PM

Answers

  • You've certainly found a feature hole in our system.

     

    You're multi-binding solution is quite clever and may be your best option. At his time, we don't have a good way to enable what you want, but I will certainly take this problem as feedback for future work.

     

    Sorry for your trouble. Thanks for the great scenario.

    Monday, July 9, 2007 6:16 PM

All replies

  • You've certainly found a feature hole in our system.

     

    You're multi-binding solution is quite clever and may be your best option. At his time, we don't have a good way to enable what you want, but I will certainly take this problem as feedback for future work.

     

    Sorry for your trouble. Thanks for the great scenario.

    Monday, July 9, 2007 6:16 PM
  • buzz,

    Funny, it's 2009 and I ran into this same problem and it seems that not too many people are doing this.  Been searching my tail off trying to figure this out.


    Much like your example, I have a treeview that contains items.  Depending on what is selected (TypeID) I wanted the content on the right hand side to be changed.

    So I originally developed a solution that would use a DataTemplateSelector class to return the proper control.  This of couse always bound to the Content property (as you mentioned).  After hours of playing, figured out a good solution.

    1) Define the ContentControl with the DataContext set to wherever is required (to be bound in the end) and bind it to your data template selector class.

    <ContentControl Name="ccEditors" Content="{Binding ElementName=treeFields, Path=SelectedItem}" DataContext="{Binding}">
      <ContentControl.ContentTemplateSelector>
        <loc:SmartFilterTemplateSel />
      </ContentControl.ContentTemplateSelector>
    </ContentControl>



    2) Create your data templates but bind their datacontext to the ContentControl

    <DataTemplate x:Key="TextTemplate"> 
      <StackPanel Name="grpText">
        <TextBox Name="txtData1" DataContext="{Binding ElementName=ccEditors, Path=DataContext}" Text="{Binding Path=Value1}" />
      </StackPanel>
    </DataTemplate>
    


     

    • Proposed as answer by EternalCoder Monday, April 26, 2010 11:30 PM
    Thursday, December 10, 2009 6:15 PM
  • Ron, thanks for the solution.  I tried it and works well!
    Monday, April 26, 2010 11:32 PM