Wprowadzenie — po co pliki?
Aplikacja traci dane po zamknięciu. Pliki pozwalają je zachować na dysku i wczytać przy kolejnym uruchomieniu.
W praktyce: notatnik (TXT), listy danych (JSON). To jest dokładnie to, czego wymaga INF.04: zapisz → zamknij → uruchom → wczytaj i pokaż.
Co tworzymy w projekcie (Visual Studio 2022)
- Dwie strony:
•TxtPage.xaml– notatnik TXT
•JsonPage.xaml– lista imion do JSON
Jak dodać stronę: Solution Explorer → prawy klik na projekt → Add → New Item → .NET MAUI ContentPage (XAML).
Część A – Notatnik TXT (zapis/odczyt jednego tekstu)
TxtPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PlikiDemo.TxtPage"
Title="Notatnik TXT">
<VerticalStackLayout Padding="16" Spacing="12">
<!-- Pole wielowierszowe: użytkownik wpisuje treść -->
<Editor x:Name="NotatkaEditor" HeightRequest="150" Placeholder="Wpisz notatkę..."/>
<!-- Dwa przyciski: zapis i odczyt pliku -->
<HorizontalStackLayout Spacing="8">
<Button Text="Zapisz" Clicked="Zapisz_Click"/>
<Button Text="Wczytaj" Clicked="Wczytaj_Click"/>
</HorizontalStackLayout>
<!-- Informacje zwrotne dla użytkownika -->
<Label x:Name="Status" TextColor="Gray"/>
</VerticalStackLayout>
</ContentPage>
TxtPage.xaml.cs
namespace PlikiDemo;
public partial class TxtPage : ContentPage
{
// 1) Wyznaczamy pełną ścieżkę do pliku w katalogu aplikacji
// FileSystem.AppDataDirectory = bezpieczne miejsce na dane (Android/iOS/Windows/macOS)
string path = Path.Combine(FileSystem.AppDataDirectory, "notatka.txt");
public TxtPage()
{
InitializeComponent(); // 2) Tworzy kontrolki z XAML i łączy je z tą klasą
}
// 3) Zapis - nadpisuje plik zawartością pola Editor
private async void Zapisz_Click(object sender, EventArgs e)
{
await File.WriteAllTextAsync(path, NotatkaEditor.Text ?? "");
Status.Text = "Zapisano plik.";
}
// 4) Odczyt - jeśli plik istnieje, wczytujemy go do Editor
private async void Wczytaj_Click(object sender, EventArgs e)
{
if (File.Exists(path))
{
NotatkaEditor.Text = await File.ReadAllTextAsync(path);
Status.Text = "Wczytano plik.";
}
else
{
Status.Text = "Plik nie istnieje (zapisz coś najpierw).";
}
}
}
Co się właśnie stało?
- Ustaliliśmy lokalizację pliku:
AppDataDirectory/notatka.txt. WriteAllTextAsynczapisało treść zEditordo pliku.ReadAllTextAsyncodczytało tekst i wstawiło go z powrotem doEditor.Statuspokazuje, co zrobiono, więc użytkownik nie błądzi.
Część B – Lista JSON (zapis/odczyt listy stringów)
JsonPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PlikiDemo.JsonPage"
Title="Lista JSON">
<VerticalStackLayout Padding="16" Spacing="10">
<!-- Wpisywanie nowej pozycji (np. imię) -->
<Entry x:Name="ImieEntry" Placeholder="Wpisz imię"/>
<Button Text="Dodaj" Clicked="Dodaj_Click"/>
<!-- Lista elementów na ekranie -->
<CollectionView x:Name="Lista" HeightRequest="200">
<CollectionView.ItemTemplate>
<DataTemplate>
<!-- Tu każdy element to zwykły string -->
<Label Text="{Binding}" FontSize="18"/>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<!-- Zapis/odczyt JSON -->
<HorizontalStackLayout Spacing="8">
<Button Text="Zapisz JSON" Clicked="ZapiszJson_Click"/>
<Button Text="Wczytaj JSON" Clicked="WczytajJson_Click"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</ContentPage>
JsonPage.xaml.cs
using System.Text.Json;
namespace PlikiDemo;
public partial class JsonPage : ContentPage
{
// 1) Ścieżka do pliku JSON w katalogu aplikacji
string path = Path.Combine(FileSystem.AppDataDirectory, "imiona.json");
// 2) Pamięciowa lista danych (RAM)
List<string> imiona = new();
public JsonPage()
{
InitializeComponent(); // tworzy kontrolki z XAML
}
// 3) Dodaj nowy element do listy (w RAM) i odśwież widok
private void Dodaj_Click(object sender, EventArgs e)
{
if (!string.IsNullOrWhiteSpace(ImieEntry.Text))
{
imiona.Add(ImieEntry.Text.Trim());
// Odświeżenie CollectionView: najpierw wyczyść, potem przypisz
Lista.ItemsSource = null;
Lista.ItemsSource = imiona;
ImieEntry.Text = "";
}
}
// 4) Zapis listy do pliku w formacie JSON
private async void ZapiszJson_Click(object sender, EventArgs e)
{
// Serialize: lista -> tekst JSON
var json = JsonSerializer.Serialize(imiona);
await File.WriteAllTextAsync(path, json);
await DisplayAlert("Informacja", "Zapisano dane do JSON.", "OK");
}
// 5) Odczyt listy z pliku JSON do RAM i odświeżenie widoku
private async void WczytajJson_Click(object sender, EventArgs e)
{
if (File.Exists(path))
{
// Odczyt tekstu i Deserialize: tekst JSON -> lista
var json = await File.ReadAllTextAsync(path);
imiona = JsonSerializer.Deserialize<List<string>>(json) ?? new List<string>();
Lista.ItemsSource = null;
Lista.ItemsSource = imiona;
}
else
{
await DisplayAlert("Informacja", "Plik nie istnieje – zapisz dane najpierw.", "OK");
}
}
}
Co się właśnie stało?
- Zbierasz dane do listy w pamięci (
List<string>). Serializezamienia listę na tekst JSON i zapisuje do pliku.Deserializewczytuje plik i tworzy z niego listę z powrotem.CollectionViewpokazuje to, co ma wItemsSource, więc po każdej zmianie odświeżamy przypisanie.
Najczęstsze błędy i szybkie naprawy
- „Plik nie istnieje” przy odczycie → najpierw zapisz, potem wczytaj.
- „Lista się nie odświeża” → zrób
Lista.ItemsSource = null; Lista.ItemsSource = imiona;. - Ścieżki buduj zawsze przez
Path.Combine(FileSystem.AppDataDirectory, "nazwa.ext"). - Puste wpisy? → Sprawdzaj
string.IsNullOrWhiteSpace(...)przed dodaniem. - Długi zapis/odczyt? → używaj async (
ReadAllTextAsync/WriteAllTextAsync), tak jak w przykładzie.
Podsumowanie
- Poznałeś najprostszy sposób zapisu i odczytu plików w MAUI:
TXT →WriteAllTextAsync/ReadAllTextAsync,
JSON →JsonSerializer.Serialize/Deserialize. - Wiesz, gdzie zapisywać:
FileSystem.AppDataDirectory. - Umiesz odświeżyć widok po zmianie danych.
- To wystarczy, żeby zaliczyć typowe zadania INF.04 związane z plikami.

