RO EN

UI pentru desktop în .NET: WPF, WinForms, WinUI 3, Avalonia sau Uno Platform?

UI pentru desktop în .NET: WPF, WinForms, WinUI 3, Avalonia sau Uno Platform? ✨ Imagine generată cu AI
Doru Bulubașa
19 octombrie 2026
34 vizualizări

Aplicația de planificare a producției are 12 ani. E scrisă în WPF, rulează pe 200 de stații din fabrică și face exact ce trebuie. Nimeni nu se plânge de ea. Apoi, într-o ședință, cineva spune fraza care declanșează un proiect de un an: „WPF e o tehnologie moartă, nu? Și ar fi bine să meargă și pe Mac-urile celor de la design.”

Urmează întrebările previzibile. O rescriem în WinUI 3, că e „noul WPF”? Trecem pe Avalonia, ca să meargă peste tot? O facem web și scăpăm de problemă? Sau o lăsăm în pace?

Acesta e al doilea articol din seria despre alegerea tehnologiei de UI. În primul articol am vorbit despre web. Acum rămânem pe desktop și în ecosistemul .NET: WinForms, WPF, WinUI 3, Avalonia și Uno Platform. Varianta cu tehnologii web pe desktop, adică Electron, Tauri și Blazor Hybrid, are un articol separat, următorul din serie.

Prima întrebare: doar Windows sau și altceva?

La web, decizia pornea de la locul în care trăiește starea UI-ului. Pe desktop, prima întrebare e mai simplă și mai brutală: aplicația trebuie să ruleze și în afara Windows-ului? Răspunsul împarte lista în două familii:

  • Doar Windows — WinForms, WPF și WinUI 3. Folosesc direct componentele Windows, se integrează perfect cu sistemul de operare și au în spate ani (sau decenii) de experiență acumulată.
  • Cross-platform — Avalonia și Uno Platform rulează pe Windows, macOS și Linux, iar ambele pot ajunge și pe mobil și în browser prin WebAssembly. Desenează singure interfața, de obicei prin Skia, în loc să folosească controalele native ale fiecărui sistem.

.NET MAUI apare și el des în discuție. Funcționează pe Windows și macOS, dar nu pe Linux, iar designul lui e gândit în primul rând pentru mobil. Îl tratăm în articolul despre aplicațiile mobile, unde îi e locul.

Dacă răspunsul onest este „doar Windows, și așa va rămâne”, nu începe cu Avalonia doar pentru că sună mai modern. Dacă răspunsul e „poate, cândva”, merită să structurezi codul astfel încât portarea să rămână posibilă. Vom vedea mai jos că asta ține mai mult de arhitectură decât de framework.

Mitul „WPF e mort”

WPF și WinForms nu sunt moarte. Sunt stabile, iar diferența e importantă. Ambele sunt open source, fac parte din .NET și primesc îmbunătățiri la fiecare versiune. Nu vor mai primi revoluții, dar o tehnologie care nu se mai schimbă radical e exact ce îți dorești pentru o aplicație care trebuie să ruleze încă zece ani.

În ultimele două versiuni de .NET, WPF a primit lucruri concrete:

  • Tema Fluent, introdusă în .NET 9, care aduce aspectul Windows 11 (colțuri rotunjite, Mica, mod luminos și întunecat) fără biblioteci externe. În .NET 10, tot mai multe controale au primit stiluri Fluent, deși Microsoft spune explicit că suportul este încă în lucru.
  • Sintaxă scurtă pentru Grid, o contribuție a comunității mult așteptată.
  • Un API de clipboard comun cu WinForms, fără BinaryFormatter, plus optimizări de performanță în zona de fonturi, resurse dinamice și parsare XAML.
<!-- App.xaml: tema Fluent, care urmează setarea sistemului -->
<Application x:Class="Planificare.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             ThemeMode="System">
</Application>

<!-- .NET 10: definiții scurte pentru rânduri și coloane -->
<Grid ColumnDefinitions="2*, *, Auto" RowDefinitions="Auto, *, 40" />

WinForms a primit și el atenție: API-uri asincrone pentru formulare și controale în .NET 9, suport experimental pentru dark mode, îmbunătățiri pentru designer și accesibilitate. Pentru o aplicație internă cu formulare și tabele, WinForms rămâne cel mai rapid mod de a ajunge de la zero la ceva funcțional, mai ales datorită designerului vizual.

// .NET 9+: actualizezi UI-ul din cod asincron, fără BeginInvoke și callback-uri
private async void btnImport_Click(object sender, EventArgs e)
{
    var rezultat = await _importService.ImportaComenziAsync();
    await lblStatus.InvokeAsync(() => lblStatus.Text = $"Importate: {rezultat.Count}");
}

Limitele lor sunt cunoscute și nu vor dispărea: rulează doar pe Windows, layout-ul în WinForms e rigid comparativ cu XAML, iar suportul pentru monitoare cu DPI mare cere încă atenție la aplicațiile vechi. Dar „e vechi” nu e un motiv de rescriere. „Nu mai putem livra ce ne cere business-ul” este.

WinUI 3: viitorul nativ pe Windows, cu asteriscuri

WinUI 3 este framework-ul pe care Microsoft îl recomandă pentru aplicațiile Windows noi. Face parte din Windows App SDK, deci nu mai depinde de versiunea sistemului de operare, cum se întâmpla cu UWP. Oferă controale Fluent moderne, randare performantă și integrare cu tot ce înseamnă Windows 11. Iar Microsoft îl folosește în propriile produse.

În 2026, proiectul s-a mișcat vizibil. Windows App SDK a trecut la linia 2.x, cu lansări lunare, iar dezvoltarea WinUI s-a mutat pe GitHub, ca parte a planului de open source anunțat în 2025. Dacă ai urmărit WinUI în anii trecuți și ai renunțat din cauza ritmului lent, merită să te uiți din nou.

Asteriscurile rămân însă reale, și trebuie cunoscute înainte de a începe:

  • Nu există designer XAML vizual. Lucrezi cu Hot Reload și Live Preview. Pentru o echipă obișnuită cu designerul din WPF sau WinForms, diferența se simte.
  • Nu există un DataGrid oficial. Pentru aplicațiile de business, pline de tabele, asta e o problemă serioasă. Există alternative din comunitate și din suitele comerciale, dar e o decizie pe care trebuie s-o iei de la început.
  • Mai sunt multe probleme deschise pe GitHub, iar unele scenarii obișnuite în WPF cer încă ocolișuri.
  • Doar Windows. Dacă macOS sau Linux apar vreodată pe listă, WinUI nu te ajută.

Concluzia practică: WinUI 3 e o alegere bună pentru o aplicație Windows nouă, de tip consumer sau utilitar, care trebuie să arate și să se comporte ca o aplicație Windows 11. Pentru o aplicație de business cu zeci de ecrane de tabele, sau pentru o aplicație WPF existentă care funcționează, costul de migrare e greu de justificat azi.

Avalonia: XAML cross-platform, cu gust de WPF

Avalonia este probabil cel mai matur framework .NET de desktop cross-platform. Sintaxa și conceptele sunt foarte apropiate de WPF: XAML, stiluri, data binding, controale templatate. Totuși, nu este o copie 1:1, iar diferențele contează la portare.

Diferența fundamentală față de WPF și WinUI este că Avalonia desenează singură fiecare pixel, prin Skia. Avantajul: aplicația arată identic pe Windows, macOS și Linux, iar bug-urile de layout nu depind de sistemul de operare. Dezavantajul: nu folosește controalele native, deci nu va arăta automat ca o aplicație macOS pe un Mac, decât dacă alegi sau construiești o temă potrivită.

Avalonia 12, lansată în aprilie 2026, a fost primul release major după aproape trei ani. Câteva lucruri relevante:

  • țintește .NET 10, iar compiled bindings sunt activate implicit, deci erorile de binding apar la compilare, nu în producție;
  • câștiguri mari de performanță la randare și la pornirea pe Android cu NativeAOT;
  • accesibilitate nativă pe Linux, un lucru rar în lumea .NET;
  • pagini de navigare integrate, utile pentru scenariile mobile.

Un detaliu care nu trebuie ratat este licențierea. Framework-ul rămâne open source, sub licență MIT, și îl poți folosi gratuit și comercial. Odată cu versiunea 12, însă, s-a schimbat oferta pentru tooling și componentele premium: nivelul Community e acum doar pentru uz necomercial, iar pentru uz comercial uneltele avansate și controalele premium sunt plătite. Verifică exact ce folosești înainte să bugetezi proiectul.

Mai există Avalonia XPF, un produs comercial separat, care rulează aplicații WPF existente pe macOS și Linux cu modificări minime. Pentru scenariul din introducere, o aplicație WPF mare care trebuie să ajungă și pe Mac, e singura variantă care evită rescrierea, iar costul licenței trebuie comparat cu costul unei portări manuale.

Uno Platform: WinUI, dar peste tot

Uno Platform pornește de la o idee diferită: implementează API-ul WinUI pe toate platformele. Scrii XAML și C# ca în WinUI 3, iar aplicația rulează pe Windows, macOS, Linux, iOS, Android și în browser, prin WebAssembly. Pe Windows poate folosi chiar WinUI, iar pe celelalte platforme desenează interfața prin Skia, ca Avalonia.

Seria 6.x a consolidat abordarea bazată pe Skia. Versiunea 6.6, din august 2026, a adus publicare Native AOT pe toate platformele desktop și mobile, un backend Vulkan opțional pentru randare, mai puțin cod XAML repetitiv și o acoperire mai largă a API-urilor WinUI. Nucleul este open source, iar în jurul lui există Uno Platform Studio, cu unelte comerciale de design și productivitate.

Uno e alegerea naturală în două situații: ai deja cod sau experiență în WinUI/UWP și vrei să ajungi pe alte platforme, sau vrei o singură bază de cod care să acopere desktop, mobil și web. Prețul este că depinzi de cât de complet și de corect a fost reimplementat WinUI pe fiecare platformă, iar pentru scenarii mai puțin obișnuite merită verificat dinainte.

Același ecran, trei framework-uri

Cel mai bun mod de a vedea cât de aproape sunt aceste framework-uri e un exemplu concret. Să luăm un ecran mic, cu o listă de comenzi și un buton de reîncărcare. Întâi ViewModel-ul, scris cu CommunityToolkit.Mvvm:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;

public partial class ComenziViewModel(IComenziService service) : ObservableObject
{
    public ObservableCollection<Comanda> Comenzi { get; } = [];

    [ObservableProperty]
    private bool seIncarca;

    [RelayCommand]
    private async Task ReincarcaAsync()
    {
        SeIncarca = true;
        Comenzi.Clear();
        foreach (var c in await service.GetComenziAsync())
            Comenzi.Add(c);
        SeIncarca = false;
    }
}

Acest cod rulează neschimbat în WPF, WinUI 3, Avalonia și Uno. Diferențele apar doar în XAML.

WPF

<StackPanel>
    <Button Content="Reîncarcă" Command="{Binding ReincarcaCommand}" />
    <ListBox ItemsSource="{Binding Comenzi}" DisplayMemberPath="Numar" />
</StackPanel>

Avalonia (cu compiled bindings)

<StackPanel x:DataType="vm:ComenziViewModel">
    <Button Content="Reîncarcă" Command="{Binding ReincarcaCommand}" />
    <ListBox ItemsSource="{Binding Comenzi}">
        <ListBox.ItemTemplate>
            <DataTemplate x:DataType="m:Comanda">
                <TextBlock Text="{Binding Numar}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

WinUI 3 și Uno Platform

<StackPanel>
    <Button Content="Reîncarcă" Command="{x:Bind ViewModel.ReincarcaCommand}" />
    <ListView ItemsSource="{x:Bind ViewModel.Comenzi}">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="m:Comanda">
                <TextBlock Text="{x:Bind Numar}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackPanel>

Lecția e mai importantă decât diferențele de sintaxă: portabilitatea ține de arhitectură, nu de framework. Dacă logica stă în ViewModel-uri și servicii, mutarea pe alt framework înseamnă rescrierea view-urilor, nu a aplicației. Dacă logica stă în code-behind, în handler-e de click de 300 de linii, orice migrare devine o rescriere completă.

Cum modernizezi o aplicație WPF sau WinForms fără s-o rescrii

Înapoi la aplicația de planificare din introducere. Rescrierea completă este aproape întotdeauna cea mai scumpă și cea mai riscantă variantă. Există un drum în pași, fiecare cu valoare proprie:

  1. Treci de pe .NET Framework pe .NET 10. Câștigi performanță, suport pe termen lung, C# modern și acces la tot ecosistemul actual. Pentru WPF și WinForms, migrarea e de obicei mult mai simplă decât pare, iar instrumentele Microsoft de modernizare automatizează o bună parte din ea.
  2. Introdu un host generic și dependency injection. Cu Microsoft.Extensions.Hosting obții configurare, logging și DI exact ca în ASP.NET Core. Codul devine testabil, iar serviciile pot fi partajate cu un eventual backend sau cu o versiune web.
  3. Scoate logica din code-behind. Ecran cu ecran, mută codul în ViewModel-uri și servicii. Este pasul cel mai lung, dar e cel care face posibile toate celelalte opțiuni de mai târziu.
  4. Modernizează aspectul. Tema Fluent în WPF sau dark mode în WinForms schimbă mult percepția utilizatorilor, cu efort mic.
  5. Adaugă funcționalități noi cu tehnologii noi. Un ecran nou poate fi construit ca o componentă Blazor găzduită în aplicația existentă prin BlazorWebView. Detaliile vin în articolul următor.
  6. Abia apoi decide dacă e nevoie de cross-platform. Cu logica separată, portarea view-urilor pe Avalonia sau Uno e un proiect controlabil. Dacă nici asta nu e fezabil, Avalonia XPF rămâne varianta de rezervă.

După fiecare pas, aplicația rămâne în producție și funcțională. E aceeași idee ca la strangler fig pattern din lumea microserviciilor: înlocuiești bucată cu bucată, nu totul deodată.

Tabelul de decizie

Situația Prima alegere Alternativă serioasă
Aplicație WPF existentă, doar Windows WPF pe .NET 10, modernizat treptat —
Aplicație WinForms existentă, unealtă internă WinForms pe .NET 10 Migrare treptată spre WPF
Unealtă internă nouă, rapidă, doar Windows WinForms sau WPF Blazor Server (web intern)
Aplicație nouă, aspect nativ Windows 11 WinUI 3 WPF cu tema Fluent
Aplicație de business nouă, multe tabele, doar Windows WPF WinUI 3 + suită comercială de controale
Desktop pe Windows, macOS și Linux Avalonia Uno Platform
Desktop, mobil și web din aceeași bază de cod Uno Platform Avalonia
Aplicație WPF mare care trebuie să ajungă pe Mac Avalonia XPF Portare treptată pe Avalonia
Experiență existentă în UWP/WinUI, nevoie de cross-platform Uno Platform Avalonia

Greșelile pe care le văd cel mai des

  • Rescrierea pentru că tehnologia e „veche”. O aplicație WPF care funcționează nu are o problemă tehnică. Are, cel mult, o problemă de percepție, care se rezolvă mult mai ieftin.
  • WinUI 3 pentru aplicații pline de tabele, fără verificare. Lipsa unui DataGrid oficial se descoperă de obicei în a treia săptămână de proiect, nu în prima zi.
  • Avalonia tratată ca WPF identic. Conceptele se transferă, codul nu întotdeauna. Stilurile, unele controale și o parte din API-uri sunt diferite. Planifică timp pentru învățare.
  • Cross-platform „pentru orice eventualitate”. Dacă toți utilizatorii sunt pe Windows, un framework cross-platform îți aduce complexitate fără beneficiu. Arhitectura curată îți păstrează opțiunea deschisă la un cost mult mai mic.
  • Logica în code-behind. Este cea mai scumpă greșeală pe termen lung, indiferent de framework, pentru că blochează orice migrare viitoare.

Recapitulare

  • WinForms și WPF sunt stabile, nu moarte. Pe .NET 10, cu tema Fluent și C# modern, rămân alegeri excelente pentru aplicații Windows de business.
  • WinUI 3 e direcția nativă pe Windows și s-a mișcat mult în 2026, dar lipsa designerului și a unui DataGrid oficial contează în aplicațiile de business.
  • Avalonia e cea mai matură opțiune cross-platform pentru desktop, cu sintaxă apropiată de WPF. Framework-ul e gratuit, dar tooling-ul comercial a devenit plătit pentru uz comercial.
  • Uno Platform duce API-ul WinUI pe toate platformele, inclusiv mobil și web.
  • MVVM și separarea logicii contează mai mult decât framework-ul ales, pentru că decid cât de scumpă va fi următoarea migrare.

În articolul următor din serie, rămânem pe desktop, dar schimbăm abordarea: aplicații desktop construite cu tehnologii web. Electron, Tauri, WebView2 și Blazor Hybrid, prin care componentele Blazor din primul articol pot ajunge într-o aplicație WPF sau WinForms existentă. Când merită să livrezi o pagină web ca aplicație desktop și când nu.