3
votes

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

1
i tried this scenerio at my end it worked just fine. Can you share the template selector code both xaml and code behind and your ListB class typeNitin
I have added more code to my original question. Please let me know if you need anything else.Krishna
don't know bro i tried it working fine here. Set the templates from dictionary and they are applied. Can you see if you are getting any binding exceptions in output window?Nitin
Not getting any Binding errors. Template Selector is definitely returning the correct template ( I put a break point and checked that when I expand the first level of the treeview) But all I get in the type 'TypeBViewModel' instead of the actual DataTemplate.Krishna
Can you send me your sample code please so that I can compare with what I am doing in my project?Krishna

1 Answers

2
votes

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