Zum Inhalt
Kuonen.UI

ScrollViewer

Zeigt einen Ausschnitt eines grösseren Inhalts: Rad (mit Umschalt waagrecht), Finger mit Trägheit und die Bildlaufleisten rollen. Je Richtung gilt Auto (Leiste nur bei Bedarf), Visible, Hidden (rollt ohne Leiste) oder Disabled (rollt nicht). ScrolleZu und ScrollIntoView rollen aus Code.

Vorführung: ScrollViewerVorführung: ScrollViewer

KXAML

ScrollViewerSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
            xmlns:x="https://ui.kuonen.org/kxaml/x"
            x:Class="Kuonen.UI.Galerie.Seiten.ScrollViewerVorfuehrung"
            Spacing="12">
  <!-- Sichtbarkeit der Leisten je Richtung umschalten. -->
  <StackPanel Orientation="Horizontal" Spacing="12">
    <RadioButton Content="Auto" GroupName="Leisten" IsChecked="True" Checked="Leisten_Checked" />
    <RadioButton Content="Visible" GroupName="Leisten" IsChecked="False" Checked="Leisten_Checked" />
    <RadioButton Content="Hidden" GroupName="Leisten" IsChecked="False" Checked="Leisten_Checked" />
    <RadioButton Content="Disabled" GroupName="Leisten" IsChecked="False" Checked="Leisten_Checked" />
  </StackPanel>
  <!-- Inhalt: 12 × 12 Farbfelder, grösser als der Ausschnitt; die Felder legt das Code-Behind in einer Schleife an. -->
  <ScrollViewer x:Name="Ausschnitt" Width="480" Height="240" HorizontalAlignment="Left"
                HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
    <Grid x:Name="Gitter" />
  </ScrollViewer>
  <!-- Aus Code rollen. -->
  <StackPanel Orientation="Horizontal" Spacing="8">
    <Button Content="Nach oben links" Click="Oben_Click" />
    <Button Content="Feld 6/6 zeigen" Click="Mitte_Click" />
    <Button Content="Versatz lesen" Click="Wo_Click" />
    <TextBlock x:Name="Lage" Text="Versatz: 0, 0" VerticalAlignment="Center" />
  </StackPanel>
</StackPanel>
ScrollViewerSeite.kxaml.cs
using System.Globalization;
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Ereignisse;
using Kuonen.UI.Layout;
using Kuonen.UI.Media;

namespace Kuonen.UI.Galerie.Seiten;

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

/// <summary>
/// KXAML-Fassung der ScrollViewer-Seite: der Rahmen steht in ScrollViewerSeite.kxaml, die 144 Felder legt der
/// Konstruktor an (Wiederholtes gehört in Code, nicht in Markup).
/// </summary>
public sealed partial class ScrollViewerVorfuehrung
{
    public ScrollViewerVorfuehrung()
    {
        InitializeComponent();
        for (int i = 0; i < 12; i++)
        {
            Gitter.RowDefinitions.Add(new RowDefinition { Height = GridLength.Pixel(60) });
            Gitter.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Pixel(90) });
        }
        for (int zeile = 0; zeile < 12; zeile++)
            for (int spalte = 0; spalte < 12; spalte++)
            {
                var feld = new Border
                {
                    Margin = new Thickness(2), CornerRadius = new CornerRadius(4),
                    Background = new SolidColorBrush(Color.FromRgb((byte)(120 + zeile * 10), (byte)(150 + spalte * 8), 220)),
                    Child = new TextBlock { Text = $"{zeile + 1}/{spalte + 1}", Foreground = new SolidColorBrush(Color.FromRgb(0x1B, 0x1B, 0x1B)), Margin = new Thickness(6) },
                };
                Grid.SetRow(feld, zeile);
                Grid.SetColumn(feld, spalte);
                Gitter.Children.Add(feld);
            }
    }

    private void ZeigeLage() => Lage.Text = string.Create(CultureInfo.InvariantCulture, $"Versatz: {Ausschnitt.Offset.X:0}, {Ausschnitt.Offset.Y:0}");

    private void Leisten_Checked(object sender, RoutedEventArgs e)
    {
        var art = (string?)((RadioButton)sender).Content switch
        {
            "Visible" => ScrollBarVisibility.Visible,
            "Hidden" => ScrollBarVisibility.Hidden,
            "Disabled" => ScrollBarVisibility.Disabled,
            _ => ScrollBarVisibility.Auto,
        };
        Ausschnitt.HorizontalScrollBarVisibility = art;
        Ausschnitt.VerticalScrollBarVisibility = art;
    }

    private void Oben_Click(object sender, RoutedEventArgs e)
    {
        Ausschnitt.ScrolleZu(default);
        ZeigeLage();
    }

    private void Mitte_Click(object sender, RoutedEventArgs e)
    {
        Ausschnitt.ScrollIntoView(new Rect(5 * 90, 5 * 60, 90, 60));
        ZeigeLage();
    }

    private void Wo_Click(object sender, RoutedEventArgs e) => ZeigeLage();
}

C#

ScrollViewerSeite.cs
using System.Globalization;
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Layout;
using Kuonen.UI.Media;

namespace Kuonen.UI.Galerie.Seiten;

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

    public override string Beschreibung =>
        "Zeigt einen Ausschnitt eines grösseren Inhalts: Rad (mit Umschalt waagrecht), Finger mit Trägheit und die "
        + "Bildlaufleisten rollen. Je Richtung gilt Auto (Leiste nur bei Bedarf), Visible, Hidden (rollt ohne Leiste) "
        + "oder Disabled (rollt nicht). ScrolleZu und ScrollIntoView rollen aus Code.";

    public override string Stichworte => "Bildlauf rollen scrollen Ausschnitt Rad Trägheit ScrollBarVisibility Auto Visible Hidden Disabled ScrolleZu";

    public override string Datei => nameof(ScrollViewerSeite);

    public override UIElement Baue()
    {
        // Inhalt: 12 × 12 Farbfelder, grösser als der Ausschnitt.
        var gitter = new Grid();
        for (int i = 0; i < 12; i++)
        {
            gitter.RowDefinitions.Add(new RowDefinition { Height = GridLength.Pixel(60) });
            gitter.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Pixel(90) });
        }
        for (int zeile = 0; zeile < 12; zeile++)
            for (int spalte = 0; spalte < 12; spalte++)
            {
                var feld = new Border
                {
                    Margin = new Thickness(2), CornerRadius = new CornerRadius(4),
                    Background = new SolidColorBrush(Color.FromRgb((byte)(120 + zeile * 10), (byte)(150 + spalte * 8), 220)),
                    Child = new TextBlock { Text = $"{zeile + 1}/{spalte + 1}", Foreground = new SolidColorBrush(Color.FromRgb(0x1B, 0x1B, 0x1B)), Margin = new Thickness(6) },
                };
                Grid.SetRow(feld, zeile);
                Grid.SetColumn(feld, spalte);
                gitter.Children.Add(feld);
            }

        var ausschnitt = new ScrollViewer
        {
            Content = gitter, Width = 480, Height = 240, HorizontalAlignment = HorizontalAlignment.Left,
            HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
        };
        var lage = new TextBlock { Text = "Versatz: 0, 0", VerticalAlignment = VerticalAlignment.Center };
        void ZeigeLage() => lage.Text = string.Create(CultureInfo.InvariantCulture, $"Versatz: {ausschnitt.Offset.X:0}, {ausschnitt.Offset.Y:0}");

        // Sichtbarkeit der Leisten je Richtung umschalten.
        var wahl = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 12 };
        foreach (var (name, art) in new[]
        {
            ("Auto", ScrollBarVisibility.Auto), ("Visible", ScrollBarVisibility.Visible),
            ("Hidden", ScrollBarVisibility.Hidden), ("Disabled", ScrollBarVisibility.Disabled),
        })
        {
            var feld = new RadioButton { Content = name, GroupName = "Leisten", IsChecked = art == ScrollBarVisibility.Auto };
            feld.Checked += (_, _) =>
            {
                ausschnitt.HorizontalScrollBarVisibility = art;
                ausschnitt.VerticalScrollBarVisibility = art;
            };
            wahl.Children.Add(feld);
        }

        // Aus Code rollen.
        var oben = new Button { Content = "Nach oben links" };
        oben.Click += (_, _) =>
        {
            ausschnitt.ScrolleZu(default);
            ZeigeLage();
        };
        var mitte = new Button { Content = "Feld 6/6 zeigen" };
        mitte.Click += (_, _) =>
        {
            ausschnitt.ScrollIntoView(new Rect(5 * 90, 5 * 60, 90, 60));
            ZeigeLage();
        };
        var wo = new Button { Content = "Versatz lesen" };
        wo.Click += (_, _) => ZeigeLage();
        var knoepfe = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8 };
        knoepfe.Children.Add(oben);
        knoepfe.Children.Add(mitte);
        knoepfe.Children.Add(wo);
        knoepfe.Children.Add(lage);

        var seite = new StackPanel { Spacing = 12 };
        seite.Children.Add(wahl);
        seite.Children.Add(ausschnitt);
        seite.Children.Add(knoepfe);
        return seite;
    }
}