Dataczwartek, 13 sierpnia 2026 Czas17:38:29
← Aplikacje mobilne (.NET MAUI)

Lekcja 7. Kontrolki II — CheckBox, RadioButton, Switch, Slider, Pickery

Średni

Po co się tego uczymy?

Formularze rzadko ograniczają się do wpisywania tekstu — potrzebujesz też kontrolek do zaznaczania opcji, wyboru z listy, dat i godzin. Ta lekcja dogłębnie omawia dziewięć kontrolek wyboru w .NET MAUI razem z pełnymi tabelami właściwości.

Teoria

CheckBox — zaznaczenie tak/nie

Właściwość Opis
IsChecked Stan zaznaczenia — logika formularza.
Color Kolor znacznika — akcent wizualny.
IsEnabled Włącza/wyłącza interakcję — np. dostępny dopiero po wypełnieniu innych pól.

RadioButton — jedna opcja z wielu

Właściwość Opis
GroupName Łączy przyciski w jedną grupę — tylko jedna opcja może być zaznaczona naraz.
Content Tekst/element wizualny obok "kropki" — opis opcji.
IsChecked Stan zaznaczenia — do odczytu wyboru.

Switch — przełącznik ON/OFF

Właściwość Opis
IsToggled Stan włącz/wyłącz.
OnColor Kolor tła w stanie ON — sygnał "aktywne".
ThumbColor Kolor "gałki" przełącznika — lepsza widoczność.

Slider — suwak wartości liczbowej

Właściwość Opis
Minimum / Maximum Zakres dopuszczalnych wartości.
Value Bieżąca wartość — wiążesz z modelem danych.
MinimumTrackColor / MaximumTrackColor Kolory toru — jasne wskazanie postępu.

Stepper — przycisk + / −

Właściwość Opis
Minimum / Maximum Dolna/górna granica — brak wartości "poza skalą".
Increment Krok zmiany wartości — decyduje o precyzji.
Value Aktualna wartość.

DatePicker i TimePicker — wybór daty i godziny

Kontrolka Kluczowe właściwości
DatePicker Date (wybrana data), Format (np. dd.MM.yyyy), MinimumDate/MaximumDate — zapobiega np. wyborowi daty urodzenia z przyszłości.
TimePicker Time (wybrana godzina), Format (HH:mm dla zapisu 24-godzinnego).

Picker — lista rozwijana

Właściwość Opis
Title Tekst zachęcający do wyboru, widoczny zanim użytkownik cokolwiek wybierze.
ItemsSource Kolekcja danych źródłowych (w wersji "produkcyjnej" częściej niż statyczne Items).
SelectedIndex / SelectedItem Pozycja albo wartość wybranego elementu.
ItemDisplayBinding Która właściwość obiektu ma być wyświetlana (np. Nazwa), gdy ItemsSource to kolekcja obiektów, a nie samych tekstów.

SearchBar — pole wyszukiwania

Właściwość Opis
Placeholder Podpowiedź wyjaśniająca, co można wyszukać.
Text Aktualnie wpisana fraza — wiążesz z logiką filtrowania.
SearchButtonPressed Zdarzenie wywoływane po naciśnięciu Enter/ikony lupy.

Schemat

Kiedy ktorej kontrolki uzyc:

CheckBox     -> zaznacz DOWOLNA liczbe opcji (0, 1, wiele)
RadioButton  -> wybierz DOKLADNIE JEDNA opcje z widocznej grupy
Switch       -> WLACZ/WYLACZ jedna opcje (jak przelacznik w telefonie)
Slider       -> wybierz wartosc z CIAGLEGO zakresu (np. glosnosc)
Stepper      -> wybierz wartosc SKOKOWO (np. liczba sztuk w koszyku)
DatePicker/TimePicker -> wybierz DATE / GODZINE z kalendarza/zegara
Picker       -> wybierz JEDNA opcje z listy ROZWIJANEJ
SearchBar    -> wpisz FRAZE do wyszukania/filtrowania

Przykład z życia

Formularz rezerwacji wizyty lekarskiej w aplikacji mobilnej używa większości tych kontrolek naraz: Picker do wyboru specjalizacji lekarza, DatePicker i TimePicker do wyboru terminu, CheckBox przy "Chcę otrzymać przypomnienie SMS", i Switch przy ustawieniu "Zapamiętaj moje dane na następny raz".

AnkietaPage.xaml

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="KontrolkiApp2.AnkietaPage">

    <ScrollView>
        <VerticalStackLayout Padding="20" Spacing="16">

            <Label Text="Płeć:" FontAttributes="Bold" />
            <HorizontalStackLayout Spacing="15">
                <RadioButton x:Name="OpcjaKobieta" Content="Kobieta" GroupName="Plec" />
                <RadioButton x:Name="OpcjaMezczyzna" Content="Mężczyzna" GroupName="Plec" />
            </HorizontalStackLayout>

            <Label Text="Ulubiony dział informatyki:" FontAttributes="Bold" />
            <Picker x:Name="ListaDzialow" Title="Wybierz dział">
                <Picker.ItemsSource>
                    <x:Array Type="{x:Type x:String}">
                        <x:String>Programowanie</x:String>
                        <x:String>Bazy danych</x:String>
                        <x:String>Sieci komputerowe</x:String>
                    </x:Array>
                </Picker.ItemsSource>
            </Picker>

            <Label x:Name="EtykietaOcena" Text="Poziom trudności: 5" FontAttributes="Bold" />
            <Slider x:Name="SuwakOcena" Minimum="1" Maximum="10" Value="5"
                    ValueChanged="SuwakOcena_ValueChanged" />

            <HorizontalStackLayout Spacing="10">
                <CheckBox x:Name="PoleZgoda" />
                <Label Text="Akceptuję regulamin ankiety" VerticalOptions="Center" />
            </HorizontalStackLayout>

            <Button x:Name="PrzyciskWyslij" Text="Wyślij ankietę" IsEnabled="False"
                    Clicked="PrzyciskWyslij_Clicked" />

        </VerticalStackLayout>
    </ScrollView>
</ContentPage>

AnkietaPage.xaml.cs

namespace KontrolkiApp2;

public partial class AnkietaPage : ContentPage
{
    public AnkietaPage()
    {
        InitializeComponent();
        // Przycisk wlaczy sie dopiero po zaznaczeniu zgody
        PoleZgoda.CheckedChanged += (s, e) => PrzyciskWyslij.IsEnabled = e.Value;
    }

    private void SuwakOcena_ValueChanged(object sender, ValueChangedEventArgs e)
    {
        // e.NewValue to nowa wartosc suwaka (typu double)
        EtykietaOcena.Text = $"Poziom trudności: {e.NewValue:F0}";
    }

    private async void PrzyciskWyslij_Clicked(object sender, EventArgs e)
    {
        string plec = OpcjaKobieta.IsChecked ? "Kobieta" : "Mężczyzna";
        string dzial = ListaDzialow.SelectedItem?.ToString() ?? "(nie wybrano)";

        await DisplayAlert("Dziękujemy!",
            $"Płeć: {plec}nDział: {dzial}nOcena trudności: {SuwakOcena.Value:F0}",
            "OK");
    }
}

Komentarz i wyjaśnienie kodu

Dwa RadioButton mają wspólne GroupName="Plec" — zaznaczenie jednego automatycznie odznacza drugi. Picker jest wypełniony na sztywno w XAML przez Picker.ItemsSource z tablicą x:Array — w bardziej zaawansowanych aplikacjach ta lista pochodziłaby z bazy danych i byłaby podpięta w kodzie C#.

Slider ma podpięte zdarzenie ValueChanged, które aktualizuje etykietę na bieżąco — e.NewValue jest typu double, dlatego formatujemy je jako {e.NewValue:F0}, żeby pokazać liczbę całkowitą bez miejsc po przecinku.

W konstruktorze strony podpinamy zdarzenie CheckedChanged checkboxa BEZPOŚREDNIO w C# (zamiast w XAML) — to alternatywny, równie poprawny sposób podłączenia obsługi zdarzenia, przydatny, gdy chcesz np. użyć wyrażenia lambda zamiast osobnej metody.

Ćwiczenie samodzielne

Utwórz stronę z powyższym kodem. Sprawdź: (1) czy zaznaczenie jednego RadioButtona odznacza drugi; (2) czy etykieta nad suwakiem aktualizuje się na bieżąco podczas przesuwania; (3) czy przycisk "Wyślij ankietę" jest zablokowany, dopóki nie zaznaczysz zgody.

Zadania do pracy własnej

  1. Dodaj do ankiety trzecią opcję RadioButton 'Wolę nie podawać' do grupy Plec.

  2. Dodaj Stepper (zakres 1-5) do wyboru 'Ile razy w tygodniu programujesz', z etykietą aktualizowaną w czasie rzeczywistym, oraz Switch 'Chcę otrzymywać powiadomienia o nowych materiałach'.

  3. Zbuduj formularz rezerwacji wizyty: Picker z listą specjalizacji, DatePicker (z MinimumDate ustawionym na dzisiaj, żeby nie dało się wybrać przeszłej daty), TimePicker, CheckBox 'Chcę przypomnienie SMS' i SearchBar do przeszukania listy dostępnych lekarzy (na razie wystarczy, że SearchButtonPressed wypisuje wpisaną frazę w Label — pełne filtrowanie poznasz przy CollectionView).

Typowe błędy

Brak wspólnego GroupName dla RadioButton — bez tego każdy przycisk działa niezależnie i można zaznaczyć kilka naraz, co przeczy idei "wybierz jedną opcję".

Brak MinimumDate/MaximumDate przy DatePicker tam, gdzie to ma sens — formularz rezerwacji bez ograniczenia dat pozwoli użytkownikowi wybrać termin w przeszłości, co jest błędem logicznym aplikacji.

Odczyt SelectedItem bez sprawdzenia null — jeśli użytkownik nic nie wybrał w Pickerze, SelectedItem będzie null; próba użycia go bez sprawdzenia (albo operatora ?.) rzuci wyjątek.

Mylenie Value (Slider/Stepper) z typem int — obie kontrolki operują na double, więc bezpośrednie przypisanie do zmiennej typu int bez rzutowania nie skompiluje się.

Nawiązanie do egzaminu zawodowego

To dalsza realizacja INF.04.6.2 w zakresie formularzy i elementów UI. Kontrolki wyboru — CheckBox, RadioButton, Switch, Picker i pozostałe — pojawiają się w niemal każdym praktycznym zadaniu egzaminacyjnym z aplikacją mobilną, szczególnie tam, gdzie trzeba zebrać ustrukturyzowane dane od użytkownika.