Zum Inhalt
Kuonen.UI

DatePicker

Ein Datumsfeld: Datum tippen (13.10.26, 1310, 2026-10-13 oder mit Monatsname) und mit der Eingabetaste oder beim Verlassen übernehmen – das Jahr steht danach immer vierstellig im Feld. Unlesbares bleibt stehen, das Feld ist rot und nennt den Grund. Knopf, Alt+Pfeil runter oder F4 öffnen den Kalender; ein Klick oder die Eingabetaste auf einem Tag wählt ihn, Esc schliesst ohne Änderung.

Vorführung: DatePickerVorführung: DatePicker

KXAML

DatePickerSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
            xmlns:x="https://ui.kuonen.org/kxaml/x"
            x:Class="Kuonen.UI.Galerie.Seiten.DatePickerVorfuehrung"
            Spacing="8">
  <TextBlock Text="Kurzes Datum" FontWeight="SemiBold" />
  <!-- Kurzes Datum, wie es das Format der Sprache schreibt; die Vorgabe der Galerie ist der 13. Oktober 2026. -->
  <DatePicker x:Name="Kurz" Width="220" HorizontalAlignment="Left" SelectedDate="2026-10-13"
              SelectedDateChanged="Kurz_SelectedDateChanged" DateValidationError="Kurz_DateValidationError" />
  <TextBlock x:Name="KurzWert" Text="Gewählt: 2026-10-13" />
  <TextBlock Text="Langes Datum" FontWeight="SemiBold" />
  <!-- Langes Datum: der Wochentag und der Monatsname stehen ausgeschrieben im Feld. -->
  <DatePicker x:Name="Lang" Width="320" HorizontalAlignment="Left" SelectedDateFormat="Long" SelectedDate="2026-10-13"
              SelectedDateChanged="Lang_SelectedDateChanged" DateValidationError="Lang_DateValidationError" />
  <TextBlock x:Name="LangWert" Text="Gewählt: 2026-10-13" />
  <TextBlock Text="Eigenes Muster (yyyy-MM-dd)" FontWeight="SemiBold" />
  <!-- Eigenes Muster: ISO 8601; das Muster bestimmt auch die Reihenfolge beim Lesen. -->
  <DatePicker x:Name="Eigen" Width="220" HorizontalAlignment="Left" SelectedDateFormat="Custom" CustomDateFormat="yyyy-MM-dd"
              SelectedDateChanged="Eigen_SelectedDateChanged" DateValidationError="Eigen_DateValidationError" />
  <TextBlock x:Name="EigenWert" Text="Gewählt: –" />
  <TextBlock Text="Anzeigebereich, gesperrter Tag und gesperrte Wochenenden" FontWeight="SemiBold" />
  <!-- Anzeigebereich Oktober 2026; der gesperrte Tag und der Wochenend-Prüfer stehen im Code-Behind. -->
  <DatePicker x:Name="Bereich" Width="220" HorizontalAlignment="Left" PlaceholderText="Werktag im Oktober"
              DisplayDateStart="2026-10-01" DisplayDateEnd="2026-10-31"
              SelectedDateChanged="Bereich_SelectedDateChanged" DateValidationError="Bereich_DateValidationError" />
  <TextBlock x:Name="BereichWert" Text="Gewählt: –" />
  <TextBlock Text="CalendarDatePicker mit Watermark" FontWeight="SemiBold" />
  <CalendarDatePicker x:Name="Cdp" Width="220" HorizontalAlignment="Left" Watermark="Datum wählen …"
                      SelectedDateChanged="Cdp_SelectedDateChanged" DateValidationError="Cdp_DateValidationError" />
  <TextBlock x:Name="CdpWert" Text="Gewählt: –" />
  <DatePicker Width="220" HorizontalAlignment="Left" IsEnabled="False" />
</StackPanel>
DatePickerSeite.kxaml.cs
using System.Globalization;
using Kuonen.UI;
using Kuonen.UI.Bindung;
using Kuonen.UI.Controls;

namespace Kuonen.UI.Galerie.Seiten;

public sealed partial class DatePickerSeite
{
    protected override Func<UIElement>? KxamlFabrik => () => new DatePickerVorfuehrung();
}

/// <summary>KXAML-Fassung der DatePicker-Seite: der Baum steht in DatePickerSeite.kxaml, hier nur das Verhalten.</summary>
public sealed partial class DatePickerVorfuehrung
{
    public DatePickerVorfuehrung()
    {
        InitializeComponent();
        // Was sich in KXAML nicht schreiben lässt: ein gesperrter Tag und der Prüfer für die Wochenenden.
        Bereich.IstGesperrt = tag => tag.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday;
        Bereich.BlackoutDates.Add(new CalendarDateRange(new DateTime(2026, 10, 15)));
    }

    private static string Datum(DateTime? tag) => tag is { } t ? t.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) : "–";

    private void Kurz_SelectedDateChanged(object sender, Kuonen.UI.Controls.SelectionChangedEventArgs e) => KurzWert.Text = "Gewählt: " + Datum(Kurz.SelectedDate);

    private void Kurz_DateValidationError(object? sender, DatePickerDateValidationErrorEventArgs e) => KurzWert.Text = "Fehler: " + Validation.GetFehler(Kurz);

    private void Lang_SelectedDateChanged(object sender, Kuonen.UI.Controls.SelectionChangedEventArgs e) => LangWert.Text = "Gewählt: " + Datum(Lang.SelectedDate);

    private void Lang_DateValidationError(object? sender, DatePickerDateValidationErrorEventArgs e) => LangWert.Text = "Fehler: " + Validation.GetFehler(Lang);

    private void Eigen_SelectedDateChanged(object sender, Kuonen.UI.Controls.SelectionChangedEventArgs e) => EigenWert.Text = "Gewählt: " + Datum(Eigen.SelectedDate);

    private void Eigen_DateValidationError(object? sender, DatePickerDateValidationErrorEventArgs e) => EigenWert.Text = "Fehler: " + Validation.GetFehler(Eigen);

    private void Bereich_SelectedDateChanged(object sender, Kuonen.UI.Controls.SelectionChangedEventArgs e) => BereichWert.Text = "Gewählt: " + Datum(Bereich.SelectedDate);

    private void Bereich_DateValidationError(object? sender, DatePickerDateValidationErrorEventArgs e) => BereichWert.Text = "Fehler: " + Validation.GetFehler(Bereich);

    private void Cdp_SelectedDateChanged(object sender, Kuonen.UI.Controls.SelectionChangedEventArgs e) => CdpWert.Text = "Gewählt: " + Datum(Cdp.SelectedDate);

    private void Cdp_DateValidationError(object? sender, DatePickerDateValidationErrorEventArgs e) => CdpWert.Text = "Fehler: " + Validation.GetFehler(Cdp);
}

C#

DatePickerSeite.cs
using System.Globalization;
using Kuonen.UI;
using Kuonen.UI.Bindung;
using Kuonen.UI.Controls;
using Kuonen.UI.Layout;

namespace Kuonen.UI.Galerie.Seiten;

/// <summary>Galerie-Seite: <see cref="DatePicker"/> und <see cref="CalendarDatePicker"/>.</summary>
public sealed partial class DatePickerSeite : GalerieSeite
{
    public override string Titel => "DatePicker";

    public override string Beschreibung =>
        "Ein Datumsfeld: Datum tippen (13.10.26, 1310, 2026-10-13 oder mit Monatsname) und mit der Eingabetaste oder beim Verlassen übernehmen – das Jahr steht danach "
        + "immer vierstellig im Feld. Unlesbares bleibt stehen, das Feld ist rot und nennt den Grund. Knopf, Alt+Pfeil runter oder F4 öffnen den Kalender; ein Klick "
        + "oder die Eingabetaste auf einem Tag wählt ihn, Esc schliesst ohne Änderung.";

    public override string Stichworte => "Datum Datumsfeld DatePicker CalendarDatePicker Kalender Klappe Watermark Platzhalter Fehler gesperrt Bereich SelectedDate";

    public override string Datei => nameof(DatePickerSeite);

    public override UIElement Baue()
    {
        static string Tag(DateTime? tag) => tag is { } t ? t.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) : "–";

        // Meldet die Wahl und einen Fehler unter dem Feld.
        static void Melde(DatePicker feld, TextBlock ausgabe)
        {
            feld.SelectedDateChanged += (_, _) => ausgabe.Text = "Gewählt: " + Tag(feld.SelectedDate);
            feld.DateValidationError += (_, _) => ausgabe.Text = "Fehler: " + Validation.GetFehler(feld);
        }

        // Kurzes Datum, wie es das Format der Sprache schreibt; die Vorgabe der Galerie ist der 13. Oktober 2026.
        var kurz = new DatePicker { Width = 220, HorizontalAlignment = HorizontalAlignment.Left, SelectedDate = new DateTime(2026, 10, 13) };
        var kurzWert = new TextBlock { Text = "Gewählt: 2026-10-13" };
        Melde(kurz, kurzWert);

        // Langes Datum: der Wochentag und der Monatsname stehen ausgeschrieben im Feld; getippt wird das Datum wie vorher.
        var lang = new DatePicker { Width = 320, HorizontalAlignment = HorizontalAlignment.Left, SelectedDateFormat = DatePickerFormat.Long, SelectedDate = new DateTime(2026, 10, 13) };
        var langWert = new TextBlock { Text = "Gewählt: 2026-10-13" };
        Melde(lang, langWert);

        // Eigenes Muster: ISO 8601; das Muster bestimmt auch die Reihenfolge beim Lesen.
        var eigen = new DatePicker { Width = 220, HorizontalAlignment = HorizontalAlignment.Left, SelectedDateFormat = DatePickerFormat.Custom, CustomDateFormat = "yyyy-MM-dd" };
        var eigenWert = new TextBlock { Text = "Gewählt: –" };
        Melde(eigen, eigenWert);

        // Anzeigebereich Oktober 2026, ein Feiertag gesperrt, Wochenenden vom Prüfer gesperrt: getippt und im Kalender nicht wählbar.
        var bereich = new DatePicker
        {
            Width = 220, HorizontalAlignment = HorizontalAlignment.Left, PlaceholderText = "Werktag im Oktober",
            DisplayDateStart = new DateTime(2026, 10, 1), DisplayDateEnd = new DateTime(2026, 10, 31),
            IstGesperrt = tag => tag.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday,
        };
        bereich.BlackoutDates.Add(new CalendarDateRange(new DateTime(2026, 10, 15)));
        var bereichWert = new TextBlock { Text = "Gewählt: –" };
        Melde(bereich, bereichWert);

        // CalendarDatePicker: die Namen von Avalonia und WinUI (Watermark statt PlaceholderText).
        var cdp = new CalendarDatePicker { Width = 220, HorizontalAlignment = HorizontalAlignment.Left, Watermark = "Datum wählen …" };
        var cdpWert = new TextBlock { Text = "Gewählt: –" };
        Melde(cdp, cdpWert);

        var seite = new StackPanel { Spacing = 8 };
        seite.Children.Add(new TextBlock { Text = "Kurzes Datum", FontWeight = 600 });
        seite.Children.Add(kurz);
        seite.Children.Add(kurzWert);
        seite.Children.Add(new TextBlock { Text = "Langes Datum", FontWeight = 600 });
        seite.Children.Add(lang);
        seite.Children.Add(langWert);
        seite.Children.Add(new TextBlock { Text = "Eigenes Muster (yyyy-MM-dd)", FontWeight = 600 });
        seite.Children.Add(eigen);
        seite.Children.Add(eigenWert);
        seite.Children.Add(new TextBlock { Text = "Anzeigebereich, gesperrter Tag und gesperrte Wochenenden", FontWeight = 600 });
        seite.Children.Add(bereich);
        seite.Children.Add(bereichWert);
        seite.Children.Add(new TextBlock { Text = "CalendarDatePicker mit Watermark", FontWeight = 600 });
        seite.Children.Add(cdp);
        seite.Children.Add(cdpWert);
        seite.Children.Add(new DatePicker { Width = 220, HorizontalAlignment = HorizontalAlignment.Left, IsEnabled = false });
        return seite;
    }
}