0

I have one model named Visit

public class Visit
{
    public int {get; set;}
    public DateTime Date {get; set;}
    public string VisitNo {get; set;}
    public string Details {get;set;}
}

How can I populate a TreeView WinUI 3 like main roots are Years and Childrens are VisitNos.

I expecting the result below.

+2022
  -0001
  -0002
+2023
  -0003
  -0004
  -0005
2
  • Can you post code for a sample data? I don't understand the items under each year. Commented Apr 26, 2023 at 22:54
  • Do you mean that you have a collection (List?) of Visists and you want to group it by Date.Year? Commented Apr 27, 2023 at 0:32

1 Answer 1

2

I guess this will do:

using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace TreeViewExample;

public class Visit
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public string VisitNo { get; set; } = string.Empty;
    public string Details { get; set; } = string.Empty;
}

public partial class YearItem : ObservableObject
{
    public YearItem(int year)
    {
        Year = year;
    }

    [ObservableProperty]
    private int year;

    [ObservableProperty]
    private ObservableCollection<Visit> visits = new();
}

public class TreeViewTemplateSelector : DataTemplateSelector
{
    public DataTemplate? YearTemplate { get; set; }

    public DataTemplate? VisitTemplate { get; set; }

    protected override DataTemplate? SelectTemplateCore(object item)
    {
        return item switch
        {
            YearItem => YearTemplate,
            Visit => VisitTemplate,
            _ => throw new NotSupportedException(),
        };
    }
}

public partial class MainPageViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<YearItem> yearItems = new();

    public MainPageViewModel()
    {
        List<Visit> visits = new()
        {
            new Visit { Id = 1, Date = DateTime.Now.AddYears(-1).AddMonths(-3), VisitNo = "001", Details = "Visit 1" },
            new Visit { Id = 2, Date = DateTime.Now.AddYears(-1), VisitNo = "002", Details = "Visit 2" },
            new Visit { Id = 3, Date = DateTime.Now.AddMonths(-2), VisitNo = "003", Details = "Visit 3" },
            new Visit { Id = 4, Date = DateTime.Now.AddMonths(-1), VisitNo = "004", Details = "Visit 4" },
            new Visit { Id = 5, Date = DateTime.Now, VisitNo = "005", Details = "Visit 5" }
        };

        foreach (Visit visit in visits)
        {
            if (YearItems
                .Where(x => x.Year == visit.Date.Year)
                .FirstOrDefault() is not YearItem visitsViewModel)
            {
                visitsViewModel = new(visit.Date.Year);
                YearItems.Add(visitsViewModel);
            }

            visitsViewModel.Visits.Add(visit);
        }
    }
}
<Page
    x:Class="TreeViewExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:TreeViewExample"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">
    <Page.DataContext>
        <local:MainPageViewModel x:Name="ViewModel" />
    </Page.DataContext>

    <Page.Resources>
        <local:TreeViewTemplateSelector x:Key="TreeViewTemplateSelector">
            <local:TreeViewTemplateSelector.YearTemplate>
                <DataTemplate x:DataType="local:YearItem">
                    <TreeViewItem
                        Content="{x:Bind Year}"
                        ItemsSource="{x:Bind Visits}" />
                </DataTemplate>
            </local:TreeViewTemplateSelector.YearTemplate>
            <local:TreeViewTemplateSelector.VisitTemplate>
                <DataTemplate x:DataType="local:Visit">
                    <TextBlock Text="{x:Bind VisitNo}" />
                </DataTemplate>
            </local:TreeViewTemplateSelector.VisitTemplate>
        </local:TreeViewTemplateSelector>
    </Page.Resources>

    <Grid>
        <TreeView
            ItemTemplateSelector="{StaticResource TreeViewTemplateSelector}"
            ItemsSource="{x:Bind ViewModel.YearItems, Mode=OneWay}" />
    </Grid>
</Page>
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much, This what I exactly want.
Great! Then can you accept the answer so we can close this section?
I already accept the answer by clicking up button. It won't show here, thanks again!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.