Úprava vzhledu čísel dnů v UWP CalendarView

Development WinUI XAML

6 years ago

Ovládací prvek CalendarView v UWP nám umožňuje v aplikaci zobrazit kalendář s mnoha funkcemi možnostmi přizpůsobení. Jak ale můžeme upravit vzhled jednotlivých dnů v měsíci? Na to se podíváme v tomto článku.

Problém

Ve výchozím stavu CalendarView zobrazuje čísla dnů v měsíci horizontálně a vertikálně vycentrované:

Default look of the CalendarView

Výchozí vzhled CalendarView

Přestože vypadá tento formát dobře, možná preferujete jiné rozložení. Například zabudovaná aplikace Outlook Kalendář používá pro čísla zarovnání nahoru doleva:

Outlook Calendar app

Aplikace Outlook Kalendář

Kde jsou moje čísla dnů?

První rychlý nápad každého vývojáře v XAMLu je, že by mělo být možné upravit výchozí styl CalendarView. Bohužel k našemu překvapení ve stylu není o číslech dnů žádná zmínka. Druhým nápadem je samozřejmě modifikovat style CalendarViewDayItemStyle. Ač se zdá, že by to mělo vést k úspěšnému výsledku, znovu narážíme na překážku. Každá změna v tomto Stylu ovliňuje oblast za číslem dne, ale ne číslo samotné. Co se děje? Odpověď má pro nás XAML Live Visual Tree explorer.

CalendarViewDayItem

CalendarViewDayItem

Prvním synem CalendarViewDayItem je obsah který vytvoříme v CalendarViewDayItem.Template kdežto druhý syn je TextBlock, který zobrazuje číslo dne. Tento TextBlock je přidán ovládacím prvkem CalendarView. Jak se k němu dostaneme?

Už zase to měníte?

Protože se data CalendarView často mění, neexistuje žádná vlastnost typu Items, přes kterou bychom mohli získat přístup přímo k jednotlivým dnům. Namísto toho je tu událost CalendarViewDayItemChanging , která je volána pokaždé, když je buď vytvořen nebo modifikován CalendarViewDayItem. Uvnitř kompaktně pojmenované třídy CalendarViewDayItemChangingEventArgs najdeme vlastnost Item přes kterou na náš CalendarViewDayItem můžeme přistoupit a najít pak uvnitř náš TextBlock. Nejprve si vytvoříme pomocnou metodu pomocí VisualTreeHelper, která najde prvního přímého potomka DependencyObject daného typu:

private T FindFirstChildOfType<T>(DependencyObject control) where T : DependencyObject
{
    var childrenCount = VisualTreeHelper.GetChildrenCount(control);
    for (int childIndex = 0; childIndex < childrenCount; childIndex++)
    {
        var child = VisualTreeHelper.GetChild(control, childIndex);
        if (child is T typedChild)
        {
            return typedChild;
        }
    }
    return null;
}

Nyní zbývá už jen jediné - najít a upravit dlouho hledaný TextBlock ku obrazu svému:

private void CalendarView_OnCalendarViewDayItemChanging(CalendarView sender, CalendarViewDayItemChanging args)
{
    var textBlock = FindFirstChildOfType<TextBlock>(args.Item);
    if (textBlock != null)
    {
        textBlock.HorizontalAlignment = HorizontalAlignment.Left;
        textBlock.VerticalAlignment = VerticalAlignment.Top;
        textBlock.Margin = new Thickness(12);
        textBlock.FontSize = 26;
        textBlock.FontWeight = FontWeights.Light;
    }
}

Et voilà - náš CalendarView je nyní plně personalizovaný:

Our beautiful customized CalendarView

Náš krásný personalizovaný CalendarView

Zdrojový kód

Ukázkový zdrojový kód k tomuto článku můžete najít na mém GitHubu.

Shrnutí

Ukázali jsme sie, jak přistupovat k jednotlivým dnům v CalendarView a jak přizpůsobit vzhled čísel dnů v měsíci pomocí CalendarViewDayItem uvnitř události CalendaryViewDayItemChanging.