wpftriggerscontenttemplatecontenttemplateselector

ItemsControl with multiple ItemTemplateSelector


I have this ScrollViewer:

<ScrollViewer x:Name="myScrollViewer">
  <ItemsControl x:Name="myItemsControl" ItemTemplateSelector="{DynamicResource myItemtemplateSelector}" ItemsPanel="{StaticResource myItemsPanel}" />
</ScrollViewer>

I fill the ItemsControl with a class that has one boolean parameter. When it's true I want to call one ItemTemplateSelector; and another one in the false case.

I'm trying something like that:

<ItemsControl x:Name="myItemsControl" ItemsPanel="{StaticResource myItemsPanel}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <ContentControl>
        <ContentControl.Style>
          <Style TargetType="{x:Type ContentControl}">
            <Style.Triggers>
              <DataTrigger Binding="{Binding Path=myBoolean}" Value="False">
                <Setter Property="ContentTemplate" Value="{DynamicResource SubdisciplineDataTemplateSelector}" />
              </DataTrigger>
              <DataTrigger Binding="{Binding Path=myBoolean}" Value="True">
                <Setter Property="ContentTemplate" Value="{DynamicResource SubdisciplineDataTemplateSelector2}" />
              </DataTrigger>
            </Style.Triggers>
          </Style>
        </ContentControl.Style>
      </ContentControl>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

Is this the right way?


Solution

  • Well, no, this line is wrong:

    <Setter Property="ContentTemplate" Value="{DynamicResource SubdisciplineDataTemplateSelector}" />
    

    You're trying to assign a DataTemplateSelector to a DataTemplate property.

    Now, there can be many ways to achieve what you want. I would create a third TemplateSelector, embedding the first two as private properties.

    Pretend that your class is something like this:

    public class MyClass { public bool MyBoolean { get; set; } }
    

    The TemplateSelector would be like this:

    public class ThirdSelector : DataTemplateSelector
    {
        private DataTemplateSelector _selector1 = new SubdisciplineDataTemplateSelector();
        private DataTemplateSelector _selector2 = new SubdisciplineDataTemplateSelector2();
    
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            var obj = item as MyClass;
    
            if (obj == null)
                return null;
    
            if (obj.MyBoolean)
                return _selector1.SelectTemplate(item, container);
            else
                return _selector2.SelectTemplate(item, container);
        }
    }
    

    This in case you want/must preserve the first two selectors. If you can get rid of them, delete them and bring all the logic to the new one.

    This is a general solution, maybe if you share more of your code and domain objects, there can be an even more suitable one for your case.