Grafikus C# – Windows Forms tanfolyam › 15.4 lecke

Továbbtanulás · 15.4 lecke · többplatformos

.NET MAUI és többplatformos alkalmazások

A Windows Forms és a WPF csak Windowson fut. De a felhasználóid telefonon, táblagépen, Macen is dolgoznak. A .NET MAUI (Multi-platform App UI) azt ígéri, hogy egyetlen C# projektből készíthetsz alkalmazást Windowsra, Androidra, iOS-re és macOS-re. A felületet itt is XAML írja le, az adatkötés és az MVVM ugyanúgy működik, mint a WPF-ben (15.3 lecke): amit tanultál, továbbvihető. Ebben a leckében áttekintjük a MAUI szerkezetét, a vezérlőit és elrendezéseit, a platformfüggő részek kezelését, a mobil világ sajátosságait (érintés, életciklus, jogosultságok), és a többplatformos alternatívákat (Avalonia, Uno Platform, Blazor Hybrid, webes alkalmazás). A cél: tudd, mikor érdemes többplatformos útra lépni, és mi a következő lépés.

  • kb. 90 perc
  • áttekintő szint
  • többplatformos
Diák C# programozást gyakorol egy tanulósarokban

A lecke végére

  • elmagyarázod, mi a .NET MAUI, és milyen platformokat céloz;
  • ismered a projekt szerkezetét (egy projekt, MauiProgram.cs, App.xaml, oldalak, Resources);
  • összeveted a MAUI-t a WPF-fel (vezérlők, elrendezések, események);
  • tudod, hogyan kezeled a platformfüggő részeket;
  • ismered a mobil sajátosságait (érintés, kijelzőméretek, életciklus, jogosultságok, tárolás);
  • ismered az alternatívákat, és megalapozottan választasz.

Mielőtt elkezded

Ehhez a leckéhez a 15.1–15.3 lecke (WPF, XAML, adatkötés, MVVM) szükséges. A MAUI kipróbálásához a Visual Studio .NET Multi-platform App UI development munkaterhelése kell; iOS-fordításhoz Mac is szükséges.

15.3 Adatkötés és MVVM →

Mi a .NET MAUI?

Egy kódbázis, több platform

A MAUI az Xamarin.Forms utódja: egyetlen projektből építhetsz Android, iOS, macOS (Mac Catalyst) és Windows (WinUI 3) alkalmazást. A felület XAML, a logika C#, a megjelenítést minden platformon a natív vezérlők végzik (Android Button, iOS UIButton), ezért az alkalmazás az adott rendszer „anyanyelvén” viselkedik.

Ismerős alapok

A C# nyelv, az XAML, az adatkötés, az INotifyPropertyChanged, az MVVM, a ICommand, az ObservableCollection és a függőség-átadás ugyanúgy használható, mint a WPF-ben. Az, hogy a 12. fejezetben a logikát felülettől független osztályokba tetted, itt hatalmas előny: újrahasználod.

Mit nem fed le?A MAUI hivatalosan nem céloz Linuxot (arra az Avalonia vagy az Uno Platform jó, lásd lent). Windowsra WinUI 3 felületet készít, amely a WPF-hez képest modernebb, de más vezérlőkészletű technológia.
Mit jelent a „natív”?A MAUI nem saját rajzolóval jeleníti meg a felületet (mint egyes keretrendszerek), hanem a rendszer vezérlőit használja: a szöveg, a gördítés, a billentyűzet, a hozzáférhetőség (képernyőolvasó) a platform szokásos módján működik.
Fejlesztői környezetWindowson Visual Studióban fejleszthetsz Androidra és Windowsra (Android-emulátorral vagy telefonnal), iOS-hez és macOS-hez Mac kell (a fordítás és a futtatás ott történik). A telepítés nagyobb (SDK-k, emulátorok), és az első fordítás lassú.
ÉrettségA MAUI fiatalabb és gyorsabban változó technológia, mint a WPF vagy a Windows Forms; verziónként előfordulnak törő változások és hibák. Új projektnél mindig a dokumentáció és a hibakövetők alapján ellenőrizd az aktuális állapotot.

Jósolj!

A programodat Windows Formsban írtad, és mobilra is szeretnéd. Átviheted a Windows Forms Formjaidat MAUI-ba változtatás nélkül? Mit vihetsz át?

Jóslat ellenőrzése

A Formokat nem (más felületi technológia), de a logikát igen: a felülettől független osztályok (modell, szolgáltatások, ViewModel) áttehetők (osztálykönyvtárba, 12. fejezet). Az új felületet újra kell építeni XAML-ben, de a program „agya” megmarad.

A projekt felépítése és a felület

Egy új MAUI projekt szerkezete (dotnet new maui)mappák
DiakMaui\
DiakMaui.csproj ← TargetFrameworks: net8.0-android;net8.0-ios;net8.0-maccatalyst;net8.0-windows...
MauiProgram.cs ← az alkalmazás összeállítása (composition root: szolgáltatások, betűtípusok)
App.xaml, App.xaml.cs ← az alkalmazás szintű erőforrások (színek, stílusok)
AppShell.xaml ← navigáció (Shell: lapok, menü)
MainPage.xaml(.cs) ← egy oldal (ContentPage)
Resources\Images, Fonts, Styles ...
Platforms\Android, iOS, MacCatalyst, Windows\ ← platformspecifikus fájlok (indítók, manifest)
MainPage.xaml (a diáklista MAUI-ban)XAML
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DiakMaui.MainPage" Title="Diáklista">

<VerticalStackLayout Padding="16" Spacing="10">
<Entry Placeholder="Új diák neve" Text="{Binding UjNev}"/>
<Button Text="Hozzáad" Command="{Binding HozzaadCommand}"/>

<CollectionView ItemsSource="{Binding Diakok}" SelectionMode="Single" SelectedItem="{Binding Kivalasztott}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Megjelenites}" Padding="8"/>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>

<Label Text="{Binding Allapot}" TextColor="Gray"/>
</VerticalStackLayout>
</ContentPage>

// MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public MainPage(MainViewModel vm) // a ViewModelt a függőség-átadás (DI) adja
{
InitializeComponent();
BindingContext = vm; // a MAUI-ban: BindingContext (a WPF DataContext megfelelője)
}
}
WPF.NET MAUI
WindowContentPage (oldal), Shell (navigáció)
TextBlockLabel
TextBoxEntry (egysoros), Editor (többsoros)
Button Content="...", ClickButton Text="...", Clicked (az eseményparaméter EventArgs)
ListBox, DataGridCollectionView (lista, rács), ListView
CheckBox, SliderCheckBox, Switch, Slider, Picker
StackPanel, Grid, DockPanelVerticalStackLayout, HorizontalStackLayout, Grid, FlexLayout
DataContextBindingContext
Margin, PaddingMargin, Padding, Spacing (az elemek köze a layoutban)
Majdnem ugyanaz, mégis másA XAML szintaxis, a kötés és az MVVM ugyanaz; a névterek más (dotnet/2021/maui), és a vezérlők nevei és tulajdonságai eltérnek (Label.Text, Button.Text, Entry). Az átállás nem újratanulás, hanem „fordítás”.
Dependency injectionA MauiProgram.cs CreateMauiApp metódusa a composition root (12.9 lecke): itt regisztrálod az oldalakat és a ViewModelt (builder.Services.AddSingleton<MainViewModel>()), és az oldal konstruktora megkapja: ez a 12.8 lecke függőség-átadása, beépítve a keretrendszerbe.
ShellAz AppShell.xaml adja a navigációt (lapok, menü, „vissza”): a mobil alkalmazások oldalról oldalra lépkednek, a Shell.Current.GoToAsync("reszletek") hívással.
Közös ViewModelA 15.3 lecke ObservableObject, RelayCommand és MainViewModel osztályai (ICommand, INotifyPropertyChanged) a MAUI-ban is használhatók: a Model és ViewModel maradhat egy közös osztálykönyvtárban, és három felület (WPF, MAUI, konzol) használhatja.

Jósolj!

A 15.3 lecke MainViewModel osztályában a ICollectionView Lista (CollectionViewSource) a WPF-re jellemző. Működik-e változtatás nélkül a MAUI-ban?

Jóslat ellenőrzése

Nem: a CollectionViewSource és az ICollectionView a WPF-hez tartozik (System.Windows.Data). A ViewModel felületfüggő részét (itt a szűrés) a MAUI-ban másképp kell megoldani (például a szűrt lista külön ObservableCollection-ben, amelyet a ViewModel maga frissít). Ezért érdemes a ViewModelt a keretrendszer-független .NET osztályokra építeni.

Platformfüggő részek kezelése

Platformfüggő kód a MAUI-banC#
// 1. FUTÁSIDEJŰ ELÁGAZÁS: melyik platformon futunk?
if (DeviceInfo.Platform == DevicePlatform.Android) { /* Android-specifikus */ }
else if (DeviceInfo.Platform == DevicePlatform.WinUI) { /* Windows */ }

// 2. FORDÍTÁSI FELTÉTEL: csak az adott platform kódja kerül a programba
#if ANDROID
// Android API hívások (Android.Content, Android.OS ...)
#elif WINDOWS
// Windows API hívások
#endif

// 3. KÖZÖS API-K (Microsoft.Maui.Essentials): ugyanaz a kód minden platformon
Preferences.Set("nyelv", "hu"); // egyszerű beállítások tárolása
string mappa = FileSystem.AppDataDirectory; // az alkalmazás adatmappája (a 14.7 lecke megfelelője)
bool van = Connectivity.NetworkAccess == NetworkAccess.Internet; // van-e internet
await Share.Default.RequestAsync(new ShareTextRequest { Text = "Szia!" }); // megosztás a rendszer ablakával

// 4. FELÜLETSZÁL: a MAUI-ban a MainThread (a WPF Dispatcher, a WinForms Invoke megfelelője)
MainThread.BeginInvokeOnMainThread(() => lblAllapot.Text = "Kész.");
Közös API-k (Essentials)A MAUI beépített Essentials részei egységes C# felületet adnak a platformfüggő funkciókhoz: Preferences, FileSystem, Connectivity, Geolocation (helymeghatározás), Camera/MediaPicker, Share, Clipboard, DeviceInfo. Ezeket használva a kódod platformfüggetlen marad.
Feltételes fordítás és mappákHa egy funkció nincs az Essentialsben, a platformspecifikus kódot a #if ANDROID blokkokba, vagy a Platforms\Android stb. mappákba teszed. Ezt az interface + platformonkénti megvalósítás mintával tartsd rendben (12.8 lecke): a közös kód az interface-t látja, és a megvalósítást a függőség-átadás adja.
AdatmappaA FileSystem.AppDataDirectory az alkalmazás privát adatmappája (Androidon és iOS-en a rendszer védi): a 14.7 lecke ApplicationData megfelelője. A telepítés és az eltávolítás szabályai platformonként mások: mobilon az alkalmazás eltávolítása törli az adatait.
Teszt minden platformonAmi az egyik platformon működik, a másikon nem biztos: mindegyiken ki kell próbálni (emulátor, valódi eszköz). A többplatformos fejlesztés nem „egyszer megírod, mindenhol futtatod, kész”: a közös rész nagy, de a platformok különbségeit kezelni kell.

Jósolj!

A programodban fix elérési útra írsz: File.WriteAllText(@"C:\Adat\mentes.json", ...). Mi történik Androidon?

Jóslat ellenőrzése

Androidon nincs C: meghajtó: a hívás kivételt dob (DirectoryNotFoundException). Platformfüggetlen kódban az elérési utat a FileSystem.AppDataDirectory adja (vagy Path.Combine a rendszer mappáival): ez is érv a központi Utak osztály mellett (14.7 lecke).

A mobil alkalmazások sajátosságai

SzempontAsztali programMobilalkalmazás
BevitelEgér és billentyűzet: hover, jobb klikk, gyorsbillentyű.Érintés: koppintás, húzás; nincs hover; a képernyő-billentyűzet eltakarja a mezőket.
KépernyőNagy, átméretezhető ablak.Kicsi, sokféle méret és tájolás (álló/fekvő); a tartalomnak alkalmazkodnia kell; biztonságos terület (kivágás, sarkok).
ÉletciklusA program fut, amíg be nem zárod.A rendszer felfüggeszti vagy kilövi a háttérbe került alkalmazást: az állapotot menteni kell (OnSleep, Window.Deactivated).
JogosultságokÁltalában nincs külön engedély.A kamera, hely, kontaktok, tárhely engedélyt kér (futás közben): Permissions.RequestAsync<...>(), és kezelni kell az elutasítást.
ErőforrásokBőséges memória és áram.Korlátozott akkumulátor, memória és hálózat: kevesebb háttérmunka, gyorsabb indulás.
HálózatÁltalában stabil.Megszakadó, lassú, mobil adat: offline mód, újrapróbálás (13.6 lecke).
TerjesztésTelepítő, ZIP (14. fejezet).Áruház (Google Play, App Store): fiók, aláírás, jóváhagyás, frissítés az áruházon át.
Tervezés mobilraNagy érintési felületek (legalább ~44–48 egység), kevés információ képernyőnként, egyszerű navigáció, olvasható betűméret, érintés-barát bevitel (megfelelő billentyűzet-típus: Keyboard="Numeric"). Egy asztali űrlap átmásolása a telefonra rossz élményt ad.
Állapot mentéseA mobilrendszer bármikor lezárhatja a háttérben lévő alkalmazást: a fontos állapotot (félig kitöltött űrlap) gyakran kell menteni (13.6, 14.7 lecke), hogy a visszatérő felhasználó ne veszítsen adatot.
EngedélykérésA felhasználó megtagadhatja az engedélyt: a program ne omoljon össze, hanem magyarázza el, mire kell, és működjön korlátozottan. A kérdés a megfelelő pillanatban, indoklással jó (nem induláskor mindenre).
AkadálymentességA mobil képernyőolvasók (TalkBack, VoiceOver) a vezérlők SemanticProperties.Description értékét olvassák: adj leírást a képeknek és gomboknak, ahogy az asztali programban az AccessibleName-et (6. fejezet).

Jósolj!

Az alkalmazásod az OnStartup helyett csak a kilépéskor menti az adatokat (ahogy a Windows Forms FormClosing eseményében). Androidon a felhasználó átvált egy másik alkalmazásra, és a rendszer memóriahiány miatt kilövi a háttérbe került programodat. Mi történik az adatokkal?

Jóslat ellenőrzése

Az adatok elvesznek: a kilövés előtt nem fut le „kilépési” esemény. Mobilon a háttérbe kerüléskor (OnSleep/Deactivated), vagy folyamatosan (változáskor) kell menteni.

Alternatívák és a választás

TechnológiaPlatformokJellemző
Windows FormsWindowsEgyszerű, gyors, űrlap-alapú asztali programokra (tanfolyamunk fő témája).
WPFWindowsTestreszabható, adatvezérelt asztali felületek, XAML, MVVM.
WinUI 3WindowsA modern Windows-natív felület (Fluent kinézet), XAML alapú; újabb, kisebb ökoszisztéma.
.NET MAUIAndroid, iOS, macOS, WindowsEgy kódbázis mobilra és asztalra; natív vezérlők; a Microsoft hivatalos többplatformos megoldása.
AvaloniaWindows, Linux, macOS, mobil, böngészőNyílt forráskódú, a WPF-hez nagyon hasonló XAML; saját rajzolású vezérlők (mindenhol azonos kinézet); a Linux-támogatás fő érve.
Uno PlatformWindows, Linux, macOS, mobil, böngészőA WinUI/XAML API-t viszi több platformra; nyílt forráskódú.
Blazor HybridMAUI, WPF, Windows FormsA felület weboldalként (HTML, CSS, Razor) készül, a natív alkalmazásba ágyazva: a webes tudás és a desktop ötvözete.
Blazor / ASP.NET (web)BöngészőWebalkalmazás C#-ban; telepítés nélkül, bárhonnan elérhető (15.5 lecke).

Hogyan válassz?

  1. Hol kell futnia? Csak Windows (Forms/WPF), vagy mobil és Mac is (MAUI), vagy Linux is (Avalonia, Uno)?
  2. Kinek készül? Belső eszköz (egyszerű), nyilvános termék (kinézet, áruház).
  3. Mi a meglévő tudás és kód? A C#, XAML, MVVM és a felülettől független logika átvihető.
  4. Mekkora a csapat és az idő? A többplatformos fejlesztés és tesztelés több munka.
  5. Kell-e telepítés? Ha nem: webalkalmazás.

Gyakorlati tanács kezdőnek

  • Először tanuld meg jól a C#-ot, az OOP-t és a rétegezést: ez a felület-független alap, és mindenhol hasznos.
  • Egy felületi technológiát ismerj mélyen (nálad: Windows Forms; a következő lépés: WPF).
  • A többplatformos technológiát egy kis projekttel próbáld ki, mielőtt nagyra vállalkozol.
  • Ellenőrizd az aktuális állapotot: ezek a technológiák gyorsan fejlődnek, a hivatalos dokumentáció és a közösség a legfrissebb forrás.

Jósolj!

A programodnak Linuxon is futnia kell, és már jól ismered a WPF XAML-t. Melyik technológia illik leginkább a tudásodhoz?

Jóslat ellenőrzése

Az Avalonia: XAML alapú, a WPF-hez nagyon hasonló, és támogatja a Linuxot (a MAUI nem céloz hivatalosan Linuxot). A WPF-tudásod nagy része átvihető; a vezérlők és az API-k kisebb eltéréseit meg kell tanulni.

📷 Képernyőkép helye

Mit tegyél ide: a MAUI alkalmazás Windows és Android emulátoron, ugyanazzal a kóddal.Javasolt fájlnév: winforms-15-4-maui.webp · Alt szöveg: A MAUI alkalmazás Windowson és Androidon

Hibakeresés: te vagy a hibadetektív

Mi a baj, és hogyan javítod?

Gondold végig az okot, és csak utána nyisd le a megoldást.

1. Fix elérési út mobilon

File.WriteAllText(@"C:\Adat\mentes.json", json);
Hiba és javítás

Androidon/iOS-en nincs C:. Használd a FileSystem.AppDataDirectory értéket (Path.Combine), vagy a központi Utak osztályt platformonként.

2. WPF-es kód a MAUI-ban

A MessageBox.Show vagy a Window nem létezik.

Ok és javítás

Ezek WPF/Windows Forms osztályok. MAUI-ban: await DisplayAlert("Cím", "Üzenet", "OK"); az oldalról, vagy szolgáltatás-interface (a ViewModelben ne hívd közvetlenül).

3. A kötés nem működik

A lista üres, nincs hiba.

Ok és javítás

Nincs beállítva a BindingContext (a WPF DataContext neve MAUI-ban BindingContext), vagy a ViewModel nincs regisztrálva a DI-ben.

4. A telefon billentyűzete eltakarja a mezőt

Az alsó mezőt nem látni gépeléskor.

Ok és javítás

A tartalmat ScrollView-ba tedd, és állítsd be az ablak bemenet-módját (Androidon adjustResize); a mezőt a tartalom felső részén helyezd el.

5. Engedély nélkül összeomlik

A kamera vagy a hely használata kivételt dob.

Ok és javítás

A manifestben (Android) vagy az Info.plistben (iOS) a jogosultságot jelezni kell, és futás közben kérni (Permissions.RequestAsync); az elutasítást kezelni.

6. Csak az egyik platformon működik

A Windowson jó funkció Androidon hibás.

Ok és javítás

Platformfüggő viselkedés (fájlrendszer, jogosultság, felületi szál). Teszteld mindegyiken; a különbségeket interface és platformonkénti megvalósítás mögé tedd, és DeviceInfo.Platform vagy #if kezelje.

Mini projekt: a diáklista ViewModelje két felülettel

A cél: bizonyítani, hogy a felületfüggetlen ViewModel és Model egyszer megírva két felületen (WPF és MAUI) is használható. Ha nincs MAUI környezeted, a B részt papíron/elemzéssel végezd:

  1. Közös osztálykönyvtár: DiakCore (net8.0, nincs UseWPF): Diak modell, ObservableObject, RelayCommand, MainViewModel, DiakViewModel.
  2. Keretrendszer-független ViewModel: alakítsd át a 15.3 lecke MainViewModel osztályát: a WPF-specifikus ICollectionView/CollectionViewSource helyett a szűrt lista külön ObservableCollection, amelyet a ViewModel maga frissít; a RelayCommand ne használja a CommandManager-t (CanExecuteChanged kézi kiváltása).
  3. A) WPF felület: DiakWpf projekt, hivatkozik a DiakCore-ra: a 15.3 XAML (ListBox ItemsSource="{Binding Szurt}").
  4. B) MAUI felület (ha van környezeted): DiakMaui projekt, hivatkozik a DiakCore-ra: a leckebeli MainPage.xaml (Entry, Button Text, CollectionView); a ViewModel regisztrálása a MauiProgram.cs-ben.
  5. Futtatás: Windowson (MAUI Windows cél) és Android-emulátoron (ha van); ugyanazt a viselkedést figyeld.
  6. Különbség-lista: táblázat: szempont, WPF, MAUI: oldal/ablak neve, vezérlők nevei, eseménynevek, DataContext/BindingContext, üzenet megjelenítése (MessageBox/DisplayAlert), mentés helye.
  7. Mobil-szempontok: írd le, mit változtatnál az űrlapon telefonra (nagyobb érintési felület, ScrollView, billentyűzet-típus, állapot mentése háttérbe kerüléskor).
  8. Következtetés: hány százaléka van a kódnak a DiakCore-ban, és hány a felületekben (sorok száma szerint)? Mit tanít ez a rétegezésről (12. fejezet)?
Megoldás megnyitása (próbáld ki előbb önállóan!)
DiakCore: RelayCommand, MainViewModel (keretrendszer-független) és a MAUI regisztrációC# / XAML
// ---- DiakCore/RelayCommand.cs (nincs WPF-függőség) ----
public class RelayCommand : ICommand
{
private readonly Action<object> vegrehajt;
private readonly Func<object, bool> lehet;

public RelayCommand(Action<object> vegrehajt, Func<object, bool> lehet = null) { this.vegrehajt = vegrehajt; this.lehet = lehet; }

public event EventHandler CanExecuteChanged;

public bool CanExecute(object p) { return lehet == null || lehet(p); }
public void Execute(object p) { vegrehajt(p); }

public void Frissit() { CanExecuteChanged?.Invoke(this, EventArgs.Empty); } // a ViewModel hívja, ha az állapot változott
}

// ---- DiakCore/MainViewModel.cs ----
public class MainViewModel : ObservableObject
{
private DiakViewModel kivalasztott;
private string ujNev = "", ujJegy = "", allapot = "Kész.", szuro = "";

public ObservableCollection<DiakViewModel> Diakok { get; } = new ObservableCollection<DiakViewModel>();
public ObservableCollection<DiakViewModel> Szurt { get; } = new ObservableCollection<DiakViewModel>(); // ezt jelenítik meg a felületek

public DiakViewModel Kivalasztott { get { return kivalasztott; } set { if (Allit(ref kivalasztott, value)) { Frissit(); } } }
public string UjNev { get { return ujNev; } set { Allit(ref ujNev, value); } }
public string UjJegy { get { return ujJegy; } set { Allit(ref ujJegy, value); } }
public string Allapot { get { return allapot; } set { Allit(ref allapot, value); } }
public string Szuro { get { return szuro; } set { if (Allit(ref szuro, value)) { SzurtFrissit(); } } }

public RelayCommand HozzaadCommand { get; }
public RelayCommand JegyCommand { get; }
public RelayCommand TorolCommand { get; }

public MainViewModel()
{
HozzaadCommand = new RelayCommand(_ => Hozzaad());
JegyCommand = new RelayCommand(_ => JegyetAd(), _ => Kivalasztott != null);
TorolCommand = new RelayCommand(_ => { Diakok.Remove(Kivalasztott); Kivalasztott = null; SzurtFrissit(); Allapot = "Törölve."; }, _ => Kivalasztott != null);
}

private void Frissit() { JegyCommand.Frissit(); TorolCommand.Frissit(); }

private void SzurtFrissit()
{
Szurt.Clear();

foreach (DiakViewModel d in Diakok.Where(x => x.Nev.IndexOf(Szuro ?? "", StringComparison.CurrentCultureIgnoreCase) >= 0)) { Szurt.Add(d); }
}

private void Hozzaad()
{
try { Diakok.Add(new DiakViewModel(new Diak(UjNev))); UjNev = ""; SzurtFrissit(); Allapot = "Diák felvéve."; }
catch (ArgumentException ex) { Allapot = ex.Message; }
}

private void JegyetAd()
{
int jegy;

if (!int.TryParse(UjJegy, out jegy)) { Allapot = "A jegy egész szám kell legyen."; return; }

try { Kivalasztott.Model.JegyetAd(jegy); Kivalasztott.Frissul(); UjJegy = ""; Allapot = "Jegy rögzítve."; }
catch (ArgumentOutOfRangeException ex) { Allapot = ex.Message; }
}
}

// ---- DiakMaui/MauiProgram.cs (részlet) ----
builder.Services.AddSingleton<MainViewModel>();
builder.Services.AddSingleton<MainPage>();

// ---- DiakMaui/MainPage.xaml: a CollectionView ItemsSource="{Binding Szurt}", SelectedItem="{Binding Kivalasztott}" ----

Megjegyzés: a DiakCore a System.ComponentModel, System.Collections.ObjectModel, System.Windows.Input (ICommand: a System.ObjectModel része, WPF nélkül is elérhető) névterekkel dolgozik. A CanExecuteChanged kézi kiváltása azért kell, mert a CommandManager.RequerySuggested WPF-specifikus. A MAUI CollectionView a SelectedItem kötést SelectionMode="Single" mellett követi. A MAUI-projekt részleteit (DI-regisztráció, oldal-összekötés) a verziónak megfelelő dokumentációban ellenőrizd.

📷 Képernyőkép helye

Mit tegyél ide: ugyanaz a ViewModel két felületen (WPF ablak és MAUI oldal).Javasolt fájlnév: winforms-15-4-kesz.webp · Alt szöveg: Ugyanaz a ViewModel két felületen

Három önálló gyakorlófeladat

Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.

1. Döntési tábla

Válassz technológiát: (a) belső nyilvántartó 20 iskolai Windows gépre; (b) a diákok telefonos jegyzetalkalmazása; (c) Linuxon és Windowson is futó segédprogram.

Egy lehetséges megoldás

(a) Windows Forms vagy WPF (egyszerű, csak Windows); (b) .NET MAUI (Android és iOS egy kódbázissal); (c) Avalonia vagy Uno Platform (Linux támogatás). Az indok minden esetben a platformigény, a közönség és az időkeret.

2. Interface a platformkülönbségre

Tervezz IFajlHely interface-t, amely platformonként más mappát ad az adatoknak.

Egy lehetséges megoldás

string AdatMappa { get; }; a Windows Forms/WPF megvalósítás %LocalAppData%\Program (14.7 lecke), a MAUI megvalósítás FileSystem.AppDataDirectory; a közös kód csak az interface-t látja, a függőség-átadás (12.8 lecke) adja a megvalósítást.

3. Mobil átalakítás

Tervezd át a 14.7-es adatbeviteli ablakot telefonra: mit változtatsz?

Egy lehetséges megoldás

Egy oszlopos elrendezés (VerticalStackLayout), nagy érintési felületek, ScrollView, megfelelő billentyűzet-típus (szám, e-mail), kevesebb mező képernyőnként (lépésenként), mentés háttérbe kerüléskor, érthető hibaüzenet.

Gyakorlótár: 6 további feladat

Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.

Alap szint

1. Mi a MAUI?

Fogalmazd meg egy mondatban.

Megoldás megnyitása

A .NET többplatformos felületkeretrendszere: egy projektből Android, iOS, macOS és Windows alkalmazás.

2. Mit viszel át?

Mit használhatsz fel egy Windows Forms programból a MAUI-ban?

Megoldás megnyitása

A felülettől független logikát (modell, szolgáltatások, ViewModel); a Formokat nem.

Közepes szint

3. Neveket

Mi a WPF TextBlock, TextBox, DataContext megfelelője a MAUI-ban?

Megoldás megnyitása

Label, Entry, BindingContext.

4. Mobil életciklus

Mikor kell menteni az állapotot?

Megoldás megnyitása

Folyamatosan vagy a háttérbe kerüléskor: a rendszer bármikor kilőheti a háttérben lévő alkalmazást, kilépési esemény nélkül.

Kihívás szint

5. Linux

Melyik megoldás céloz Linuxot a felsoroltak közül: MAUI, Avalonia, WPF?

Megoldás megnyitása

Az Avalonia (és az Uno Platform); a MAUI hivatalosan nem, a WPF pedig csak Windows.

6. Engedélykérés

Hogyan kezeled, ha a felhasználó megtagadja a kamera használatát?

Megoldás megnyitása

Nem omlik össze: elmagyarázza, mire kellene, és korlátozott funkcióval működik tovább (vagy a beállításokba irányít); az elutasítás kezelése a kód része.

Gyors önellenőrzés

Válaszolj fejben, és csak utána nyisd le a választ.

1. Mik a MAUI célplatformjai?

Android, iOS, macOS (Mac Catalyst) és Windows.

2. Mi a Shell?

A MAUI navigációs szerkezete (lapok, menü, vissza).

3. Hogyan kezeled a platformkülönbséget?

Közös API-k (Essentials), DeviceInfo.Platform, #if és platformmappák, interface + megvalósítás.

4. Mi a mobil egyik fő eltérése?

Érintés, kis képernyő, életciklus, jogosultságok, korlátozott erőforrások.

5. Mi a Blazor Hybrid?

Webes felület (HTML/Razor) natív alkalmazásba ágyazva.

6. Miért előny a rétegezés?

A felülettől független logika több felületen újrahasználható.

7. Hogyan választasz technológiát?

Platformigény, közönség, meglévő tudás és kód, csapat és idő, telepítési igény szerint.

Mit tudsz már?

  • Érted a .NET MAUI célját, szerkezetét és kapcsolatát a WPF-fel.
  • Tudod, hogyan kezeled a platformfüggő részeket és a mobil sajátosságait.
  • Ismered az alternatívákat (Avalonia, Uno, Blazor Hybrid), és megalapozottan választasz.
  • Látod, hogy a felülettől független logika és ViewModel több felületen újrahasználható.

Következő lecke: Desktop és webes felületek különbsége

Mikor jobb a telepített program, mikor a webalkalmazás, és mi a szerepe a böngészőnek és a szervernek.