This is a migrated thread and some comments may be shown as answers.

Binding with HierarchicalDataTemplate

1 Answer 170 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
nico
Top achievements
Rank 1
nico asked on 22 Jul 2010, 10:38 PM
Hi,

I've some problem with my treeview, idk if my problem is directly from the treeview or not.
What i'ld like to do is somethink like this :
- Website 1
- Month A
- picture 1
- picture 2
- Month B
- picture 1
- Website 2
- Month A
- picture 1

The problem i've meet is that for all node "website", i've the same child nodes.
Thx :)

Here is my code :
MainWindow.xaml
<Window xmlns:my="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation"  x:Class="BonjourWPF.MainWindow"
        xmlns:local="clr-namespace:BonjourWPF"
        xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        Title="MainWindow" Height="768" Width="1024">
    <Window.Resources>
        <local:WebSites x:Key="WebsiteCollection" />
 
        <CollectionViewSource
            x:Key="Sites"
            Source="{Binding Source={StaticResource WebsiteCollection}}">
        </CollectionViewSource>
        <CollectionViewSource
                            x:Key="GroupMonth"
                            Source="{Binding Source={StaticResource Sites},Path=Pictures}">
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription PropertyName="date"></scm:SortDescription>
            </CollectionViewSource.SortDescriptions>
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="month" />
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="256" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid Grid.Row="0">
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition Height="256" />
            </Grid.RowDefinitions>
            <Grid.Resources>
                <DataTemplate x:Key="Picture" DataType="Picture">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding date, StringFormat={}{0:dd/MM/yyyy}}"  Foreground="Black" />
                    </StackPanel>
                </DataTemplate>
 
                <HierarchicalDataTemplate x:Key="Mois" ItemsSource="{Binding Path=Items}" ItemTemplate="{StaticResource Picture}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Name}" Foreground="Black" />
                    </StackPanel>
                </HierarchicalDataTemplate>
 
                <HierarchicalDataTemplate x:Key="Site" ItemsSource="{Binding Source={StaticResource GroupMonth},Path=Groups}"  ItemTemplate="{StaticResource Mois}">
                    <StackPanel Orientation="Horizontal">
                        <Image Source="{Binding icon}" Margin="0,0,6,0"/>
                        <TextBlock Text="{Binding name}"  Foreground="Black" FontWeight="Bold"
                            FontSize="15" />
                    </StackPanel>
                </HierarchicalDataTemplate>
 
            </Grid.Resources>
 
            <my:RadTreeView Name="RadTreeView1" ItemsSource="{Binding Source={StaticResource Sites}}" ItemTemplate="{StaticResource Site}" IsSingleExpandPath="True">
            </my:RadTreeView>
             
        </Grid>
        <Image Grid.Column="1" Name="image1" Stretch="Uniform" />
    </Grid>
</Window>


public class WebSites : ObservableCollection<WebSite>
{
    public WebSites()
    {
        this.Add(new WebSite()
        {
            id = 1,
            name = "Site 1",
            icon = "site1.ico"
        });
 
        this.Add(new WebSite()
        {
            id = 2,
            name = "Site 2",
            icon = "site2.ico"
        });
    }
}

public class Picture
{
    public DateTime date { get; set; }
    public String year
    {
        get
        {
            return date.Year.ToString();
        }
    }
    public String month
    {
        get
        {
            return DateTimeFormatInfo.CurrentInfo.GetMonthName(date.Month);
        }
 
    }
    public String path { get; set; }
}

    public class WebSite
    {
        public Int32 id { get; set; }
        public String name { get; set; }
        public String icon { get; set; }
 
        public WebSite()
        {
        }
 
 
        private ObservableCollection<Picture> _pictures;
        public ObservableCollection<Picture> Pictures
        {
            get {
                if (_pictures == null)
                {
                    _pictures = new ObservableCollection<Picture>();
                    if (Directory.Exists(name))
                    {
                        foreach (String file in Directory.GetFiles(name))
                        {
                            _pictures.Add(new Picture() { date = Convert.ToDateTime(Path.GetFileNameWithoutExtension(file)), path = Path.GetFullPath(file) });
                        }
                    }
                }
                return _pictures;
            }
            set
            {
                _pictures = value;
            }
        }
}

1 Answer, 1 is accepted

Sort by
0
Hristo
Telerik team
answered on 23 Jul 2010, 02:25 PM
Hi nico,

I can provide you two solutions to your problem. I'm attaching you an archive containing three projects.

The first one (_Bad) is similar to the code you posted.

The second one (_InModel) demonstrates how to solve the problem with grouping done in the model (ViewModel). Take a look at the WebSite.cs file.
public Object PicturesByMonth
{
    get
    {
        var result =
            from p in Pictures
            group p by new { p.month } into pg
            select new { Month = pg.Key, Items = pg };
        return result;
    }
}
In the MainWindow.xaml file you can see that I'm using normal HierarchicalDataTemplates. Notice I'm using the PicturesByMonth property to define the ItemSource for second level.

The third project (_ValueConverter) shows an alternative and uses IValueConverter interface to group the elements.
public class MonthGroupingConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var result =
            from picture in value as IEnumerable<Picture>
            group picture by new { picture.month } into GroupedPictures
            select new { Month = GroupedPictures.Key, Items = GroupedPictures };
        return result;
        }
...
MonthGroupingConverter is a custom defined class and you can change the grouping to fit your needs.

Next I'm creating an instance of it in the main mxml file.
...
<local:MonthGroupingConverter x:Key="MGC" />
...

Finally I'm using that converter in the root level template to define ItemSource for second level.
<HierarchicalDataTemplate x:Key="SiteTemplate"
        ItemsSource="{Binding Pictures,  Converter={StaticResource MGC}}"
        ItemTemplate="{StaticResource MonthsTemplate}">
    <TextBlock Text="{Binding name}" Foreground="Black" FontWeight="Bold" FontSize="15" />
</HierarchicalDataTemplate>


Sincerely yours,
Hristo
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
Tags
TreeView
Asked by
nico
Top achievements
Rank 1
Answers by
Hristo
Telerik team
Share this question
or