Zum Inhalt
Kuonen.UI

ListBox

Eine Liste zum Auswählen. Sie legt nur die sichtbaren Zeilen an, darum kostet eine Liste mit 100 000 Zeilen nicht mehr als eine mit zehn. Einzeln, mehrfach oder wie im Explorer (Strg und Umschalt) auswählen; Pfeile, Pos1, Ende und Bild auf/ab bewegen den Fokus.

Vorführung: ListBoxVorführung: ListBox

KXAML

ListBoxSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
            xmlns:x="https://ui.kuonen.org/kxaml/x"
            xmlns:local="using:Kuonen.UI.Galerie.Seiten"
            x:Class="Kuonen.UI.Galerie.Seiten.ListBoxVorfuehrung"
            Spacing="12">
  <!-- Auswahlmodus wählen. -->
  <StackPanel Orientation="Horizontal" Spacing="12">
    <RadioButton Content="Einzeln" GroupName="ListBoxModus" IsChecked="False" Checked="Modus_Checked" />
    <RadioButton Content="Mehrfach" GroupName="ListBoxModus" IsChecked="False" Checked="Modus_Checked" />
    <RadioButton Content="Wie im Explorer" GroupName="ListBoxModus" IsChecked="True" Checked="Modus_Checked" />
  </StackPanel>
  <!-- 100 000 Zeilen aus einem statischen Feld (x:Static); die Liste legt nur die sichtbaren Zeilen an. -->
  <ListBox x:Name="Liste" Width="240" Height="200" ItemsSource="{x:Static local:ListBoxVorfuehrung.Zeilen}" SelectionMode="Extended"
           SelectionChanged="Liste_SelectionChanged" />
  <StackPanel Orientation="Horizontal" Spacing="8">
    <Button Content="Alle auswählen" Click="Alle_Click" />
    <Button Content="Aufheben" Click="Keine_Click" />
    <Button Content="Zum Ende" Click="Ende_Click" />
  </StackPanel>
  <TextBlock x:Name="Meldung" Text="Nichts ausgewählt." />
</StackPanel>
ListBoxSeite.kxaml.cs
using System.Globalization;
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Ereignisse;

namespace Kuonen.UI.Galerie.Seiten;

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

/// <summary>KXAML-Fassung der ListBox-Seite: der Baum steht in ListBoxSeite.kxaml, hier die Daten und das Verhalten.</summary>
public sealed partial class ListBoxVorfuehrung
{
    /// <summary>Die Zeilen der Liste (im KXAML über x:Static).</summary>
    public static readonly string[] Zeilen = Baue();

    public ListBoxVorfuehrung() => InitializeComponent();

    private static string[] Baue()
    {
        var zeilen = new string[100_000];
        for (int i = 0; i < zeilen.Length; i++) zeilen[i] = $"Zeile {(i + 1).ToString("N0", CultureInfo.InvariantCulture)}";
        return zeilen;
    }

    private void Liste_SelectionChanged(object sender, SelectionChangedEventArgs e) => Meldung.Text = Liste.SelectedItems.Count switch
    {
        0 => "Nichts ausgewählt.",
        1 => $"Ausgewählt: {Liste.SelectedItem}.",
        var n => $"{n.ToString("N0", CultureInfo.InvariantCulture)} Zeilen ausgewählt.",
    };

    private void Modus_Checked(object sender, RoutedEventArgs e)
    {
        Liste.UnselectAll();
        Liste.SelectionMode = (string?)((RadioButton)sender).Content switch
        {
            "Einzeln" => SelectionMode.Single,
            "Mehrfach" => SelectionMode.Multiple,
            _ => SelectionMode.Extended,
        };
    }

    private void Alle_Click(object sender, RoutedEventArgs e) => Liste.SelectAll();

    private void Keine_Click(object sender, RoutedEventArgs e) => Liste.UnselectAll();

    private void Ende_Click(object sender, RoutedEventArgs e) => Liste.ScrollIntoView(Zeilen[^1]);
}

C#

ListBoxSeite.cs
using System.Globalization;
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Layout;

namespace Kuonen.UI.Galerie.Seiten;

/// <summary>Galerie-Seite: <see cref="ListBox"/>.</summary>
public sealed partial class ListBoxSeite : GalerieSeite
{
    public override string Titel => "ListBox";

    public override string Beschreibung =>
        "Eine Liste zum Auswählen. Sie legt nur die sichtbaren Zeilen an, darum kostet eine Liste mit 100 000 Zeilen nicht "
        + "mehr als eine mit zehn. Einzeln, mehrfach oder wie im Explorer (Strg und Umschalt) auswählen; Pfeile, Pos1, Ende "
        + "und Bild auf/ab bewegen den Fokus.";

    public override string Stichworte => "Liste Auswahl SelectionMode Single Multiple Extended SelectedItems Virtualisierung Zeilen";

    public override string Datei => nameof(ListBoxSeite);

    public override UIElement Baue()
    {
        var zeilen = new string[100_000];
        for (int i = 0; i < zeilen.Length; i++) zeilen[i] = $"Zeile {(i + 1).ToString("N0", CultureInfo.InvariantCulture)}";
        var meldung = new TextBlock { Text = "Nichts ausgewählt." };
        var liste = new ListBox { Width = 240, Height = 200, ItemsSource = zeilen, SelectionMode = SelectionMode.Extended };
        liste.SelectionChanged += (_, _) => meldung.Text = liste.SelectedItems.Count switch
        {
            0 => "Nichts ausgewählt.",
            1 => $"Ausgewählt: {liste.SelectedItem}.",
            var n => $"{n.ToString("N0", CultureInfo.InvariantCulture)} Zeilen ausgewählt.",
        };

        // Auswahlmodus wählen.
        var modi = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 12 };
        foreach (var (name, modus) in new[]
        {
            ("Einzeln", SelectionMode.Single), ("Mehrfach", SelectionMode.Multiple), ("Wie im Explorer", SelectionMode.Extended),
        })
        {
            var feld = new RadioButton { Content = name, GroupName = "ListBoxModus", IsChecked = modus == SelectionMode.Extended };
            feld.Checked += (_, _) =>
            {
                liste.UnselectAll();
                liste.SelectionMode = modus;
            };
            modi.Children.Add(feld);
        }

        var alle = new Button { Content = "Alle auswählen" };
        alle.Click += (_, _) => liste.SelectAll();
        var keine = new Button { Content = "Aufheben" };
        keine.Click += (_, _) => liste.UnselectAll();
        var ende = new Button { Content = "Zum Ende" };
        ende.Click += (_, _) => liste.ScrollIntoView(zeilen[^1]);
        var knoepfe = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8 };
        knoepfe.Children.Add(alle);
        knoepfe.Children.Add(keine);
        knoepfe.Children.Add(ende);

        var seite = new StackPanel { Spacing = 12 };
        seite.Children.Add(modi);
        seite.Children.Add(liste);
        seite.Children.Add(knoepfe);
        seite.Children.Add(meldung);
        return seite;
    }
}