C# · WPF · INF.04 · Kontrolki

Slider – suwak

Poznasz Slider – kontrolkę do wybierania wartości liczbowej przez przesuwanie uchwytu. Nauczysz się ustawiać zakres, kroki skokowe i powiązywać suwak z innymi kontrolkami na żywo.

Slider Minimum/Maximum/Value TickFrequency ValueChanged
1

Czym jest Slider?

Slider to suwak – kontrolka, w której użytkownik wybiera wartość liczbową, przesuwając uchwyt wzdłuż linii. Znasz go z regulacji głośności, jasności ekranu, czy ustawień w grach komputerowych.

Kiedy Slider, a kiedy TextBox?

Slider jest świetny, gdy ważny jest szybki, intuicyjny wybór z określonego zakresu (głośność, jasność, procent). TextBox lepiej sprawdza się, gdy potrzebna jest precyzyjna, konkretna wartość wpisana z klawiatury (cena, wiek, dokładna liczba).

Najprostszy Slider
<Slider x:Name="sldGlosnosc"
        Width="200" />
<!-- Domyślnie: Minimum=0, Maximum=10 -->
2

Minimum, Maximum, Value

Trzy najważniejsze właściwości Slidera określają jego zakres i aktualną wartość.

WłaściwośćCo określaWartość domyślna
MinimumNajmniejsza możliwa wartość0
MaximumNajwiększa możliwa wartość10
ValueAktualna wartość suwaka0
Slider z określonym zakresem
<!-- Głośność: 0-100, startowo 50 -->
<Slider x:Name="sldGlosnosc"
        Minimum="0"
        Maximum="100"
        Value="50"
        Width="250" />

<!-- Temperatura: -20 do 40 stopni -->
<Slider x:Name="sldTemperatura"
        Minimum="-20"
        Maximum="40"
        Value="20"
        Width="250" />

<!-- Ocena gwiazdkowa: 1-5 -->
<Slider x:Name="sldOcena"
        Minimum="1"
        Maximum="5"
        Value="3"
        Width="150" />
Value to double, nie int!

Właściwość Value jest typu double – domyślnie suwak może przyjąć wartości z przecinkiem (np. 47.36), nie tylko liczby całkowite. Jeśli chcesz tylko liczb całkowitych, użyj IsSnapToTickEnabled opisanego w sekcji 4.

3

Orientation – kierunek suwaka

Domyślnie Slider jest poziomy. Możesz go obrócić na pionowy ustawiając Orientation="Vertical" – wtedy musisz też zwykle ustawić Height zamiast Width.

Slider poziomy i pionowy
<!-- Poziomy (domyślny) -->
<Slider Orientation="Horizontal"
        Minimum="0" Maximum="100"
        Width="250" />

<!-- Pionowy – jak korektor graficzny w odtwarzaczu muzyki -->
<Slider Orientation="Vertical"
        Minimum="0" Maximum="100"
        Height="200" />
4

Znaczki skali – TickFrequency

TickFrequency ustawia odstęp między małymi znaczkami (kreseczkami) widocznymi na suwaku – pomagają one wizualnie ocenić wybraną wartość bez patrzenia na liczbę.

TickPlacement – gdzie pokazać znaczki

WartośćGdzie pokazują się znaczki
None (domyślne)Brak znaczków
TopLeftNad suwakiem (lub po lewej przy pionowym)
BottomRightPod suwakiem (lub po prawej przy pionowym)
BothZ obu stron
Slider ze znaczkami co 10
<Slider x:Name="sldGlosnosc"
        Minimum="0"
        Maximum="100"
        Value="50"
        TickFrequency="10"
        TickPlacement="BottomRight"
        Width="250" />
<!-- Znaczki widoczne przy 0, 10, 20, 30 ... 100 -->

IsSnapToTickEnabled – przyciąganie do znaczków

Sam TickFrequency tylko rysuje znaczki – nie ogranicza wartości. Żeby suwak faktycznie skakał tylko po znaczkach (np. tylko wielokrotności 10), potrzebujesz dodatkowo IsSnapToTickEnabled="True".

Slider przyciągany do znaczków – tylko pełne dziesiątki
<Slider x:Name="sldGlosnosc"
        Minimum="0"
        Maximum="100"
        Value="50"
        TickFrequency="10"
        TickPlacement="BottomRight"
        IsSnapToTickEnabled="True"
        Width="250" />
<!-- Teraz Value będzie wyłącznie wielokrotnością 10:
     0, 10, 20, 30 ... 100 – nigdy np. 47 -->
Slider tylko z liczbami całkowitymi (1-5, ocena gwiazdkowa)

Częste zastosowanie IsSnapToTickEnabled to ocena w skali 1-5 lub 1-10 – nie chcemy, żeby użytkownik mógł wybrać „3.7 gwiazdki”. Ustawienie TickFrequency="1" razem z IsSnapToTickEnabled="True" daje skok po każdej liczbie całkowitej.

Ocena gwiazdkowa – tylko liczby całkowite
<Slider x:Name="sldOcena"
        Minimum="1"
        Maximum="5"
        Value="3"
        TickFrequency="1"
        TickPlacement="BottomRight"
        IsSnapToTickEnabled="True"
        Width="180" />
<!-- Wartości: tylko 1, 2, 3, 4 lub 5 -->
5

Zdarzenie ValueChanged

ValueChanged odpala się za każdym razem gdy zmienia się wartość suwaka – podczas przesuwania, kliknięcia na linii, a także po ustawieniu wartości z kodu C#.

XAML – podpięcie zdarzenia
<Slider x:Name="sldGlosnosc"
        Minimum="0"
        Maximum="100"
        Value="50"
        Width="250"
        ValueChanged="sldGlosnosc_ValueChanged" />
C# – obsługa zmiany wartości
private void sldGlosnosc_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    // e.NewValue – nowa wartość, e.OldValue – wartość przed zmianą
    double nowaWartosc = e.NewValue;

    lblGlosnosc.Text = $"Głośność: {nowaWartosc:F0}%";
}
RoutedPropertyChangedEventArgs<double> – długa nazwa, proste użycie

Nie musisz pamiętać tej nazwy – Visual Studio wygeneruje ją automatycznie po dwukrotnym kliknięciu pola ValueChanged we właściwościach Slidera w designerze. Najważniejsze to e.NewValue, czyli aktualna wartość po zmianie.

ValueChanged odpala się też przy starcie okna!

Gdy XAML ustawia Value="50", zdarzenie ValueChanged odpala się natychmiast przy tworzeniu okna. Jeśli metoda obsługująca odwołuje się do innych kontrolek (np. lblGlosnosc), które jeszcze nie istnieją – dodaj zabezpieczenie if (lblGlosnosc == null) return;.

6

Powiązanie z TextBlock na żywo

Najczęstszy wzorzec użycia Slidera: pokazujesz aktualną wartość liczbową obok suwaka, żeby użytkownik widział precyzyjnie co właśnie wybrał.

Slider + TextBlock z wartością na żywo
<StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Głośność: " VerticalAlignment="Center" />
        <TextBlock x:Name="lblWartosc"
                   Text="50%"
                   FontWeight="Bold"
                   Foreground="SteelBlue"
                   VerticalAlignment="Center" />
    </StackPanel>

    <Slider x:Name="sldGlosnosc"
            Minimum="0"
            Maximum="100"
            Value="50"
            Width="250"
            ValueChanged="sldGlosnosc_ValueChanged" />
</StackPanel>
C# – aktualizacja TextBlock przy każdej zmianie
private void sldGlosnosc_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    if (lblWartosc == null) return;

    lblWartosc.Text = $"{e.NewValue:F0}%";
}
Format :F0 – zaokrąglanie do liczby całkowitej

{e.NewValue:F0} formatuje liczbę z przecinkiem jako liczbę całkowitą (0 cyfr po przecinku). :F1 dałoby jedno miejsce po przecinku (np. „47.3″), :F2 – dwa miejsca (np. „47.36″). Format F oznacza „fixed point” (liczba zmiennoprzecinkowa o ustalonej precyzji).

Możesz też zrobić odwrotną synchronizację – TextBox jako edytowalne pole, które aktualizuje Slider:

Dwustronna synchronizacja TextBox ↔ Slider
private bool _aktualizujeProgramowo = false;

private void sldGlosnosc_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    if (_aktualizujeProgramowo) return;
    _aktualizujeProgramowo = true;
    txtGlosnosc.Text = $"{e.NewValue:F0}";
    _aktualizujeProgramowo = false;
}

private void txtGlosnosc_TextChanged(object sender, TextChangedEventArgs e)
{
    if (_aktualizujeProgramowo) return;

    if (double.TryParse(txtGlosnosc.Text, out double wartosc))
    {
        _aktualizujeProgramowo = true;
        sldGlosnosc.Value = wartosc;
        _aktualizujeProgramowo = false;
    }
}
7

Kroki – SmallChange i LargeChange

Te właściwości kontrolują o ile zmieni się wartość Slidera po naciśnięciu klawiszy strzałek albo kliknięciu na linię suwaka (bez przesuwania uchwytu).

WłaściwośćKiedy działaWartość domyślna
SmallChangeStrzałki ⬅️➡️ na klawiaturze (gdy Slider ma focus)0.1 × (Maximum - Minimum)
LargeChangeKliknięcie na linię suwaka poza uchwytem(Maximum - Minimum)
Konfiguracja kroków
<Slider x:Name="sldGlosnosc"
        Minimum="0"
        Maximum="100"
        Value="50"
        SmallChange="1"     <!-- strzałka: +/- 1 -->
        LargeChange="10"   <!-- klik na linię: +/- 10 -->
        Width="250" />
8

Slider w C#

Typowe operacje na Sliderze z kodu
// Odczyt aktualnej wartości
double glosnosc = sldGlosnosc.Value;

// Ustawienie wartości z kodu (np. po wczytaniu zapisanych ustawień)
sldGlosnosc.Value = 75;

// Zmiana zakresu w czasie działania programu
sldGlosnosc.Minimum = 0;
sldGlosnosc.Maximum = 200;

// Reset do wartości minimalnej
sldGlosnosc.Value = sldGlosnosc.Minimum;

// Konwersja na int, gdy potrzebujesz liczby całkowitej
int glosnoscInt = (int)sldGlosnosc.Value;
9

Praktyczne przykłady

Regulacja głośności z ikoną

Panel regulacji głośności
<StackPanel Orientation="Horizontal" Margin="10">
    <TextBlock x:Name="lblIkona"
               Text="🔊"
               FontSize="18"
               Margin="0,0,8,0"
               VerticalAlignment="Center" />
    <Slider x:Name="sldGlosnosc"
            Minimum="0" Maximum="100" Value="60"
            Width="150"
            VerticalAlignment="Center"
            ValueChanged="sldGlosnosc_ValueChanged" />
    <TextBlock x:Name="lblWartosc"
               Text="60%"
               Width="40"
               Margin="8,0,0,0"
               VerticalAlignment="Center" />
</StackPanel>
C# – zmiana ikony w zależności od głośności
private void sldGlosnosc_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    if (lblWartosc == null) return;

    lblWartosc.Text = $"{e.NewValue:F0}%";

    // Zmieniamy ikonę głośnika w zależności od wartości
    if (e.NewValue == 0)
        lblIkona.Text = "🔇";
    else if (e.NewValue < 50)
        lblIkona.Text = "🔉";
    else
        lblIkona.Text = "🔊";
}

Mieszacz kolorów RGB

Trzy slidery (Red, Green, Blue) sterujące kolorem tła – klasyczne ćwiczenie łączące Slider z manipulacją kolorami.

XAML – trzy slidery RGB
<StackPanel Margin="20">

    <TextBlock Text="Red" />
    <Slider x:Name="sldRed"   Minimum="0" Maximum="255" Value="128" ValueChanged="Kolor_ValueChanged" />

    <TextBlock Text="Green" Margin="0,8,0,0" />
    <Slider x:Name="sldGreen" Minimum="0" Maximum="255" Value="128" ValueChanged="Kolor_ValueChanged" />

    <TextBlock Text="Blue" Margin="0,8,0,0" />
    <Slider x:Name="sldBlue"  Minimum="0" Maximum="255" Value="128" ValueChanged="Kolor_ValueChanged" />

    <Border x:Name="borderKolor"
            Height="80"
            Margin="0,16,0,0"
            CornerRadius="8" />

    <TextBlock x:Name="lblKodKoloru"
               Text="#808080"
               HorizontalAlignment="Center"
               Margin="0,8,0,0" />
</StackPanel>
C# – łączenie trzech sliderów w jeden kolor
private void Kolor_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    if (borderKolor == null) return;

    byte r = (byte)sldRed.Value;
    byte g = (byte)sldGreen.Value;
    byte b = (byte)sldBlue.Value;

    Color kolor = Color.FromRgb(r, g, b);
    borderKolor.Background = new SolidColorBrush(kolor);

    lblKodKoloru.Text = $"#{r:X2}{g:X2}{b:X2}";
}
Format :X2 – liczba szesnastkowa

{r:X2} formatuje liczbę jako szesnastkową (hex), z minimum 2 cyframi (uzupełnia zerem jeśli trzeba). 128 w formacie X2 da "80" – dlatego trzy takie wartości razem dają standardowy kod koloru jak #808080.

10

Częste błędy

❌ Błąd 1: TickFrequency bez IsSnapToTickEnabled

❌ Znaczki widoczne, ale nie działają

<Slider TickFrequency="10"
        TickPlacement="BottomRight" />
<!-- Znaczki na 0,10,20...
     ale wartość wciąż może być
     np. 23.7! -->

✅ Razem z IsSnapToTickEnabled

<Slider TickFrequency="10"
        TickPlacement="BottomRight"
        IsSnapToTickEnabled="True" />

❌ Błąd 2: ValueChanged odpalający się przed inicjalizacją kontrolek

❌ Wyjątek przy starcie okna

private void sld_ValueChanged(...)
{
    // lblWartosc może być null
    // gdy XAML ustawia Value="50"
    // podczas tworzenia okna!
    lblWartosc.Text = "...";
}

✅ Zabezpieczenie null

private void sld_ValueChanged(...)
{
    if (lblWartosc == null) return;
    lblWartosc.Text = "...";
}

❌ Błąd 3: Rzutowanie double na int bez przemyślenia

❌ Utrata precyzji niezauważona

int wartosc = (int)sldOcena.Value;
// Jeśli Value = 3.9, wynik to 3!
// Rzutowanie (int) zawsze
// OBCINA, nie zaokrągla

✅ Math.Round gdy potrzebne zaokrąglenie

int wartosc = (int)Math.Round(sldOcena.Value);
// 3.9 zaokrągli się do 4

// Lub po prostu użyj
// IsSnapToTickEnabled="True",
// żeby Value było zawsze całkowite

❌ Błąd 4: Zapomniany format liczby w TextBlock

❌ Brzydki wynik z wielu cyfr po przecinku

lblWartosc.Text = $"{e.NewValue}%";
// Wyświetli np. "47.36281%" –
// nieczytelne dla użytkownika

✅ Formatowanie do liczby całkowitej

lblWartosc.Text = $"{e.NewValue:F0}%";
// Wyświetli "47%"
11

Zadania do wykonania

Zadanie 1 łatwe

Stwórz Slider regulujący jasność (0-100) z TextBlock pokazującym aktualną wartość w formacie „Jasność: 75%” aktualizowanym na żywo. Gdy wartość spadnie poniżej 20, TextBlock ma zmienić kolor na czerwony (ostrzeżenie „bardzo ciemno”), powyżej – na normalny.

Zadanie 2 łatwe

Stwórz Slider oceny produktu w skali 1-5 z IsSnapToTickEnabled="True" i TickFrequency="1". Pod suwakiem wyświetl odpowiednią liczbę gwiazdek (np. dla wartości 3: „⭐⭐⭐☆☆”), aktualizowaną przy każdej zmianie.

Zadanie 3 średnie

Zbuduj kompletny mieszacz kolorów RGB (jak w sekcji 9b) z trzema sliderami, podglądem koloru w Border i kodem szesnastkowym. Dodaj dodatkowo przyciski z trzema gotowymi kolorami (np. „Czerwień”, „Zieleń”, „Błękit”), które po kliknięciu ustawiają wszystkie trzy slidery na odpowiednie wartości.

Zadanie 4 średnie

Stwórz kalkulator raty kredytu: dwa slidery – kwota kredytu (1000-100000 zł, krok 1000) i liczba miesięcy (6-60, krok 6). Pod suwakami wyświetl obliczoną miesięczną ratę (prosty wzór: kwota / liczba miesięcy, bez odsetek) oraz całkowitą kwotę do spłaty. Wynik aktualizuje się przy zmianie obu sliderów.