Custom Template based off node items

6 posts, 1 answers
  1. Mark Peterson
    Mark Peterson avatar
    8 posts
    Member since:
    Feb 2010

    Posted 20 May 2010 Link to this post

    Hello Telerik!

    I would like to change the HierarchicalDataTemplate based off what level the user is currently on.  I am referencing a modified example that was done with the League, Division, Team example.

    In my example I would like to have the treeview have the division level use the "OtherDivision" template if there are no items below.

    Thanks!
    Mark

    <Window x:Class="WpfApplication6.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:local="clr-namespace:WpfApplication6" 
        xmlns:Telerik="http://schemas.telerik.com/2008/xaml/presentation"
        <Grid> 
            <Grid.Resources> 
               
                <local:LeaguesDataSource x:Key="MyList" /> 
     
                <HierarchicalDataTemplate x:Key="Division" ItemsSource="{Binding Teams}"
                    <StackPanel Orientation="Horizontal"
                        <TextBlock Text="{Binding Name}" FontSize="12" /> 
                    </StackPanel> 
                </HierarchicalDataTemplate> 
     
                <HierarchicalDataTemplate x:Key="OtherDivision" ItemsSource="{Binding Teams}"
                    <StackPanel Orientation="Horizontal"
                        <TextBlock Text="{Binding Name}" FontSize="26" /> 
                    </StackPanel> 
                </HierarchicalDataTemplate> 
     
                <HierarchicalDataTemplate x:Key="League" ItemTemplate="{StaticResource Division}" 
                        ItemsSource="{Binding Divisions}"
                    <StackPanel Orientation="Horizontal"
                        <TextBlock Text="{Binding Name}" Foreground="Black" FontSize="15" /> 
                    </StackPanel> 
                </HierarchicalDataTemplate> 
     
                <local:LeagueDataTemplateSelector x:Key="myDataTemplateSelector"  
                    LeagueTemplate="{StaticResource League}" 
                    DivisionTemplate="{StaticResource Division}" 
                    OtherDivisionTemplate="{StaticResource OtherDivision}" 
                 /> 
                 
            </Grid.Resources> 
             
            <Grid Width="300" Height="320"
     
                    <Telerik:RadTreeView  
                        VerticalAlignment="Top" 
                        ItemsSource="{Binding Source={StaticResource MyList}}" 
                        ItemTemplateSelector="{StaticResource myDataTemplateSelector}"     
                        /> 
     
            </Grid> 
        </Grid> 
    </Window> 
     
    Code Behind
    using System; 
    using System.Collections.Generic; 
    using System.IO; 
    using System.Text; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Data; 
    using System.Windows.Documents; 
    using System.Windows.Input; 
    using System.Windows.Media; 
    using System.Windows.Media.Imaging; 
    using System.Windows.Shapes; 
    using System.Xml.Linq; 
    using System.Linq; 
     
    namespace WpfApplication6 
        /// <summary> 
        /// Interaction logic for MainWindow.xaml 
        /// </summary> 
        public partial class MainWindow : Window 
        { 
            public MainWindow() 
            { 
                InitializeComponent(); 
            } 
        } 
     
        public class League 
        { 
            public League(string name) 
            { 
                _name = name; 
                _divisions = new List<Division>(); 
            } 
     
     
            string _name; 
     
            public string Name { get { return _name; } } 
     
            List<Division> _divisions; 
            public List<Division> Divisions { get { return _divisions; } } 
     
        } 
     
        public class Division 
        { 
            public Division(string name) 
            { 
                _name = name; 
                _teams = new List<Team>(); 
     
            } 
     
            string _name; 
     
            public string Name { get { return _name; } } 
     
            List<Team> _teams; 
     
            public List<Team> Teams { get { return _teams; } } 
     
        } 
     
        public class Team 
        { 
            public Team(string name) 
            { 
                _name = name; 
            } 
     
            string _name; 
     
            public string Name { get { return _name; } } 
        } 
     
        public class LeaguesDataSource : List<League> 
        { 
            public LeaguesDataSource() 
            { 
                League leagueA = new League("League A"); 
                League leagueB = new League("League B"); 
     
                Division leagueADivisionA = new Division("Division A"); 
                leagueA.Divisions.Add(leagueADivisionA); 
     
                Division leagueADivisionB = new Division("Division B"); 
                leagueA.Divisions.Add(leagueADivisionB); 
     
                Division leagueADivisionC = new Division("Division C"); 
                leagueA.Divisions.Add(leagueADivisionC); 
     
                Division leagueBDivisionA = new Division("Division A"); 
                leagueBDivisionA.Teams.Add(new Team("Team 1")); 
                leagueBDivisionA.Teams.Add(new Team("Team 2")); 
                leagueBDivisionA.Teams.Add(new Team("Team 3")); 
                leagueBDivisionA.Teams.Add(new Team("Team 4")); 
                leagueBDivisionA.Teams.Add(new Team("Team 5")); 
     
                leagueB.Divisions.Add(leagueBDivisionA); 
     
                Division leagueBDivisionB = new Division("Division B"); 
                leagueBDivisionB.Teams.Add(new Team("Team Diamond")); 
                leagueBDivisionB.Teams.Add(new Team("Team Heart")); 
                leagueBDivisionB.Teams.Add(new Team("Team Club")); 
                leagueBDivisionB.Teams.Add(new Team("Team Spade")); 
     
                leagueB.Divisions.Add(leagueBDivisionB); 
     
                Division leagueBDivisionC = new Division("Division C"); 
                leagueBDivisionC.Teams.Add(new Team("Team Alpha")); 
                leagueBDivisionC.Teams.Add(new Team("Team Beta")); 
                leagueBDivisionC.Teams.Add(new Team("Team Gamma")); 
                leagueBDivisionC.Teams.Add(new Team("Team Delta")); 
                leagueBDivisionC.Teams.Add(new Team("Team Epsilon")); 
     
                leagueB.Divisions.Add(leagueBDivisionC); 
     
                this.Add(leagueA); 
                this.Add(leagueB); 
            } 
        } 
     
        public class LeagueDataTemplateSelector : DataTemplateSelector 
        { 
            private HierarchicalDataTemplate leagueTemplate; 
            private HierarchicalDataTemplate divisionTemplate; 
            private HierarchicalDataTemplate otherDivisionTemplate; 
     
            public LeagueDataTemplateSelector() 
            { 
            } 
            public override DataTemplate SelectTemplate(object item, DependencyObject container) 
            { 
                if (item is League) 
                    return this.leagueTemplate; 
                else if (item is Division) 
                    return this.divisionTemplate; 
                return null; 
            } 
            public HierarchicalDataTemplate LeagueTemplate 
            { 
                get 
                { 
                    return this.leagueTemplate; 
                } 
                set 
                { 
                    this.leagueTemplate = value
                } 
            } 
            public HierarchicalDataTemplate DivisionTemplate 
            { 
                get 
                { 
                    return this.divisionTemplate; 
                } 
                set 
                { 
                    this.divisionTemplate = value
                } 
            } 
     
            public HierarchicalDataTemplate OtherDivisionTemplate 
            { 
                get 
                { 
                    return this.otherDivisionTemplate; 
                } 
                set 
                { 
                    this.otherDivisionTemplate = value
                } 
            } 
            
        } 

  2. Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 25 May 2010 Link to this post

    Hello Mark Peterson,

    I am not sure if I understand your scenario correctly. When you say "use the "OtherDivision" template if there are no items below", do you mean if there are no teams in that division?

    If this is the case, then you can modify the LeagueDataTemplateSelector to apply the OtherDivisionTemplate whenever there are no Teams in the current item of type Division.

    I prepared a sample project illustrating this approach. I also added a DataTemplate for the Team items. Take a look at the attachment and let me know if this is what you had in mind or if you need more info.

    Sincerely yours,
    Tina Stancheva
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  3. UI for WPF is Visual Studio 2017 Ready
  4. Mark Peterson
    Mark Peterson avatar
    8 posts
    Member since:
    Feb 2010

    Posted 25 May 2010 Link to this post

    That works perfect but I found out a way to break this example that I am using in my actual project.  If I add an ItemContainerStyle to my treeview control and add a template, the binding is lost.  How can I fix this?

    Thanks so much for the help. 
    Mark

    I am only adding the xaml as the code behind has not changed.

    <Grid> 
            <Grid.Resources> 
             
                <ControlTemplate x:Key="RadTreeViewItemControlTemplate" TargetType="{x:Type Telerik:RadTreeViewItem}"
                    <Grid x:Name="RootElement" MinWidth="300"
                        <Grid.RowDefinitions> 
                            <RowDefinition Height="Auto"/> 
                            <RowDefinition/> 
                        </Grid.RowDefinitions> 
                        <Grid x:Name="HeaderRow" MinHeight="{TemplateBinding MinHeight}" SnapsToDevicePixels="True" Background="Transparent"
                            <Grid.ColumnDefinitions> 
                                <ColumnDefinition Width="Auto"/> 
                                <ColumnDefinition Width="Auto"/> 
                                <ColumnDefinition Width="Auto"/> 
                                <ColumnDefinition Width="Auto"/> 
                                <ColumnDefinition Width="Auto"/> 
                                <ColumnDefinition Width="*"/> 
                            </Grid.ColumnDefinitions> 
                            <Border Grid.ColumnSpan="6" Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="0" /> 
                            <Border x:Name="MouseOverVisual" Opacity="0"  Grid.ColumnSpan="6" Background="Red" BorderBrush="Transparent" BorderThickness="0" /> 
     
                            <Border x:Name="SelectionUnfocusedVisual" Visibility="Collapsed" Grid.ColumnSpan="6" BorderBrush="Transparent" Background="Transparent" BorderThickness="0" /> 
     
                            <Border x:Name="SelectionVisual" Visibility="Collapsed" Grid.ColumnSpan="6" BorderBrush="Transparent" Background="Blue" BorderThickness="0" /> 
     
                            <StackPanel x:Name="IndentContainer" Orientation="Horizontal"
                                <Rectangle x:Name="IndentFirstVerticalLine" /> 
                            </StackPanel> 
                            <Grid x:Name="ListRootContainer" HorizontalAlignment="Center" MinWidth="20" Grid.Column="1"
                                <ToggleButton x:Name="Expander" Background="{TemplateBinding Background}" IsTabStop="False"/> 
                                <Grid x:Name="LoadingVisual" HorizontalAlignment="Center" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" Visibility="Collapsed"
                                    <Grid.RenderTransform> 
                                        <TransformGroup> 
                                            <RotateTransform Angle="0" CenterX="0.5" CenterY="0.5"/> 
                                        </TransformGroup> 
                                    </Grid.RenderTransform> 
                                    <Path Stretch="Fill" Stroke="{TemplateBinding Foreground}" StrokeStartLineCap="Round" StrokeThickness="1" Width="10" Height="10" Data="M1,0A1,1,90,1,1,0,-1"/> 
                                    <Path Fill="{TemplateBinding Foreground}" Stretch="Fill" StrokeThickness="1" HorizontalAlignment="Left" Margin="5,-1.5,0,0" VerticalAlignment="Top" Width="4" Height="4" Data="M0,-1.1L0.1,-1 0,-0.9"/> 
                                </Grid> 
                            </Grid> 
                            <CheckBox x:Name="CheckBoxElement" Margin="5,0,0,0" VerticalAlignment="Center" IsTabStop="False" Visibility="Collapsed" Grid.Column="2"
                            </CheckBox> 
                            <RadioButton x:Name="RadioButtonElement" Margin="5,0,0,0" VerticalAlignment="Center" IsTabStop="False" Visibility="Collapsed" Grid.Column="2"
                            </RadioButton> 
                            <Image x:Name="Image" HorizontalAlignment="Center" Margin="2" MaxHeight="16" MaxWidth="16" VerticalAlignment="Center" Grid.Column="3" Source="{TemplateBinding DefaultImageSrc}"/> 
                            <Rectangle x:Name="FocusVisual"/> 
                            <Grid Grid.Column="4" Grid.ColumnSpan="2"
                                <ContentPresenter x:Name="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Header}" ContentTemplate="{TemplateBinding HeaderTemplate}"/> 
                                <ContentPresenter x:Name="EditHeaderElement" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Visibility="Collapsed" ContentTemplate="{TemplateBinding HeaderEditTemplate}"/> 
                            </Grid> 
                        </Grid> 
                        <ItemsPresenter x:Name="ItemsHost" Visibility="Collapsed" Grid.Row="1" /> 
                    </Grid> 
                    <ControlTemplate.Triggers> 
                        <Trigger Property="IsInEditMode" Value="True"
                            <Setter Property="Visibility" TargetName="Header" Value="Collapsed"/> 
                            <Setter Property="Visibility" TargetName="EditHeaderElement" Value="Visible"/> 
                        </Trigger> 
                        <Trigger Property="IsSelected" Value="True"
                            <Setter Property="Visibility" TargetName="SelectionVisual" Value="Visible"/> 
                            <Setter Property="BorderThickness" Value="1" /> 
                        </Trigger> 
                        <Trigger Property="IsFocused" Value="True"
                            <Setter Property="Visibility" TargetName="FocusVisual" Value="Visible"/> 
                        </Trigger> 
                        <MultiTrigger> 
                            <MultiTrigger.Conditions> 
                                <Condition Property="IsSelected" Value="True"/> 
                                <Condition Property="IsSelectionActive" Value="False"/> 
                            </MultiTrigger.Conditions> 
                            <Setter Property="Opacity" TargetName="SelectionVisual" Value="1"/> 
                            <Setter Property="Visibility" TargetName="SelectionUnfocusedVisual" Value="Visible"/> 
                        </MultiTrigger> 
                        <Trigger Property="IsEnabled" Value="False"
                            <Setter Property="Opacity" TargetName="Header" Value="0.5"/> 
                        </Trigger> 
                        <Trigger Property="IsExpanded" Value="True"
                            <Setter Property="Visibility" TargetName="ItemsHost" Value="Visible"/> 
                        </Trigger> 
                        <Trigger Property="IsLoadingOnDemand" Value="True"
                            <Trigger.EnterActions> 
                                <BeginStoryboard> 
                                    <Storyboard> 
                                        <DoubleAnimation Duration="00:00:01" RepeatBehavior="Forever" Storyboard.TargetName="LoadingVisualAngleTransform" Storyboard.TargetProperty="Angle" From="0" To="359"/> 
                                    </Storyboard> 
                                </BeginStoryboard> 
                            </Trigger.EnterActions> 
                            <Setter Property="Visibility" TargetName="LoadingVisual" Value="Visible"/> 
                            <Setter Property="Visibility" TargetName="Expander" Value="Collapsed"/> 
                        </Trigger> 
                        <Trigger Property="IsDragOver" Value="True"
                            <Setter Property="Opacity" TargetName="MouseOverVisual" Value="1"/> 
                        </Trigger> 
                        <Trigger Property="IsMouseOver" SourceName="HeaderRow" Value="True"
                            <Setter Property="Opacity" TargetName="MouseOverVisual" Value="1"/> 
                        </Trigger> 
                    </ControlTemplate.Triggers> 
                </ControlTemplate> 
     
                <Style TargetType="{x:Type Telerik:RadTreeViewItem}" x:Key="RadTreeViewItemStyle" > 
                    <Setter Property="Background" Value="Transparent" /> 
                    <Setter Property="BorderThickness" Value="0" /> 
                    <Setter Property="Template" Value="{StaticResource RadTreeViewItemControlTemplate}" /> 
                </Style> 
     
                <local:LeaguesDataSource x:Key="MyList" /> 
     
                <DataTemplate x:Key="TeamTemplate"
                    <TextBlock Text="{Binding Name}" Foreground="Red" /> 
                </DataTemplate> 
     
                <HierarchicalDataTemplate x:Key="Division" ItemsSource="{Binding Teams}"
                    <StackPanel Orientation="Horizontal"
                        <TextBlock Text="{Binding Name}" FontSize="12" /> 
                    </StackPanel> 
                </HierarchicalDataTemplate> 
     
                <HierarchicalDataTemplate x:Key="OtherDivision" ItemsSource="{Binding Teams}"
                    <StackPanel Orientation="Horizontal"
                        <TextBlock Text="{Binding Name}" FontSize="26" /> 
                    </StackPanel> 
                </HierarchicalDataTemplate> 
     
                <HierarchicalDataTemplate x:Key="League" ItemsSource="{Binding Divisions}"
                    <StackPanel Orientation="Horizontal"
                        <TextBlock Text="{Binding Name}" Foreground="Black" FontSize="15" /> 
                    </StackPanel> 
                </HierarchicalDataTemplate> 
     
                <local:LeagueDataTemplateSelector x:Key="myDataTemplateSelector"   
                                                  LeagueTemplate="{StaticResource League}"  
                                                  DivisionTemplate="{StaticResource Division}"  
                                                  OtherDivisionTemplate="{StaticResource OtherDivision}"  
                                                  TeamTemplate="{StaticResource TeamTemplate}"                     
                 /> 
     
            </Grid.Resources> 
     
            <Grid> 
     
                <Telerik:RadTreeView   
                        VerticalAlignment="Top"  
                        ItemContainerStyle="{StaticResource RadTreeViewItemStyle}"  
                        ItemsSource="{Binding Source={StaticResource MyList}}"  
                        ItemTemplateSelector="{StaticResource myDataTemplateSelector}"      
                        /> 
     
            </Grid> 
        </Grid> 



  5. Answer
    Tina Stancheva
    Admin
    Tina Stancheva avatar
    3298 posts

    Posted 28 May 2010 Link to this post

    Hello Mark Peterson,

    The binding breaks because the template you set in the ItemContainerStyle has a higher priority than the ItemTemplateSelector set in the RadTreeView.

    However, you can try another approach. you can use only one template for the Division items, but set, for example two TextBlocks in it:
    <HierarchicalDataTemplate x:Key="Division" ItemsSource="{Binding Teams}" ItemTemplate="{StaticResource TeamTemplate}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}" FontSize="12" />
            <TextBlock Text="{Binding Name}" FontSize="26" />
        </StackPanel>
    </HierarchicalDataTemplate>

    Then you can set the Visibility of each TextBlock to the Teams.Count property and use a converter to determine which TextBlock to be displayed:
    <HierarchicalDataTemplate x:Key="Division" ItemsSource="{Binding Teams}" ItemTemplate="{StaticResource TeamTemplate}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}" FontSize="12" Visibility="{Binding Teams.Count, Converter={StaticResource MyDivisionConverter}}"/>
            <TextBlock Text="{Binding Name}" FontSize="26" Visibility="{Binding Teams.Count, Converter={StaticResource MyOtherDivisionConverter}}"/>
        </StackPanel>
    </HierarchicalDataTemplate>

    I modified the example to illustrate this approach. Give it a try and let me know if it works for you.

    Kind regards,
    Tina Stancheva
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  6. Mark Peterson
    Mark Peterson avatar
    8 posts
    Member since:
    Feb 2010

    Posted 28 May 2010 Link to this post

    That works great.  Only one question left :)

    I am using xml instead of object binding in my real example.  I was going down the path of checking if my attribute was not blank for the next level ( Binding XPath=Level2/@name ) but that was only working for the first item.

    How do you do a count with xml data binding?  

    Thanks
    Mark


  7. Mark Peterson
    Mark Peterson avatar
    8 posts
    Member since:
    Feb 2010

    Posted 28 May 2010 Link to this post

    Solved my problem.

    I was able to use a {Binding .}

    My converter was changed to

    var node = ((XmlElement)value);
    return (node.ChildNodes.Count == 0) ? Visibility.Visible : Visibility.Collapsed;

    Thanks for all the help
    Mark
Back to Top
UI for WPF is Visual Studio 2017 Ready