Question

I am trying to create a simple 2 level Treeview in WPF (MVVM approach). For my first level I have a standard datatemplate, for my second level I want to use a Template Selector so that I can change the appearance of each item based on one of its properties.

Below is my Treeview xaml

<Treeview ItemsSource={Binding ListA}>
      <TreeView.ItemTemplate>
       <HierarchicalDataTemplate ItemsSource="{Binding ListB}" ItemTemplateSelector={StaticResource TemplateSelector}>
         <Textblock Text={Binding Name}/>
      </HierarchicalDataTemplate>
   </TreeView.ItemTemplate>
</TreeView>

My first level is

<Textblock Text={Binding Name}/> 

will just display a name

For my second level the TemplateSelector is returning a datatemplate which is something like

<DataTemplate x:Key="SomeKey">
<StackPanel Orientation="Horizontal">
<ViewBox>
-----
</ViewBox>
<TextBlock Text={Binding Name}/>
</StackPanel>
</DataTemplate>

But all I see for my second level is my second level ViewModel name. I double checked the template selector and it is definitely returning the correct data template but it is just not getting displayed.

Can anyone please point me in the right direction?

Edit -- Added more code as per request

this is my template selector

public class DataFieldsDataTemplateSelector : DataTemplateSelector
{
public DataTemplate AlphaTemplate { get; set; }
public ------
public ------
public DataFieldsDataTemplateSelector()
{
//This is getting the template from my ResourceDictionary
AlphaTemplate = (DataTemplate)dDictionary["alphaTemplate"];
}
public override DataTemplate SelectTemplate(object item,DependencyObject container)
        {
//Somecode
return AlphaTemplate;
}
}

my template for AlphaTemplate in my dictionary is

<DataTemplate x:Key="alphaTemplate">

            <Grid >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="15"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Viewbox  IsHitTestVisible="False">

                    <Path Data="M0,0L56.622002,0 56.622002,14.471 35.715,14.471 35.715,64 20.715,64 20.715,14.471 0,14.471z" Stretch="Uniform" Fill="{DynamicResource ButtonForegroundNormal}" VerticalAlignment="Center" Width="15" Height="15" Margin="0,0,0,0" RenderTransformOrigin="0.5,0.5">
                        <Path.RenderTransform>
                            <TransformGroup>
                                <TransformGroup.Children>
                                    <RotateTransform Angle="0" />
                                    <ScaleTransform ScaleX="1" ScaleY="1" />
                                </TransformGroup.Children>
                            </TransformGroup>
                        </Path.RenderTransform>
                    </Path>

                </Viewbox>
                <textBlock Text="{Binding Name}/>
            </Grid>
    </DataTemplate>

my class TypeB contains a Name(Text) and DataType(Text) Fields if the DataType is Alpha I return AlphaTemplate in my templateSelector and so on

I have an action(dragDrop) on the window which adds items to the second level. And I want the template selector should pick up the correct datatemplate for that dropped item based on its DataType

My main ViewModel contains ICollectionView of TypeA Objects and Each TypeA ViewModel contains ICollectionView of TypeB ViewModels.

Let me know if you need anything

Was it helpful?

Solution

I dont know what is wrong with this as this will require to debug the code, but what you wanted to achieve can be done by defining the default DataTemplate for your TypeB and switching the content depending on the binding like this:

<DataTemplate DataType="{x:Type TypeB}">
    <ContentControl>
        <ContentControl.Style>
            <Style TargetType="{x:Type ContentControl}">
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <!-- Default template here for your item -->
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding XYZ}" Value="true">
                        <Setter Property="ContentTemplate">
                            <Setter.Value>
                                <!-- Different template for your item -->
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>        
</DataTemplate>

Thanks

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top