.NET MAUI ในปี 2026: การพัฒนา Cross-Platform และคำถามสัมภาษณ์งาน

บทความสอน .NET MAUI ครอบคลุมการพัฒนา cross-platform ด้วย .NET 10, handler architecture, MVVM, HybridWebView และคำถามสัมภาษณ์งานที่สำคัญในปี 2026

.NET MAUI cross-platform development tutorial 2026

.NET MAUI (Multi-platform App UI) ได้พัฒนาจนกลายเป็น framework cross-platform ระดับ production ด้วย .NET 10 ในฐานะเวอร์ชัน Long-Term Support ที่ได้รับการสนับสนุนจนถึงเดือนพฤศจิกายน 2028 .NET MAUI 10 มาพร้อมกับ workload และแพ็กเกจ NuGet มอบการปรับปรุงด้านคุณภาพ ประสิทธิภาพ และ API ใหม่อย่าง HybridWebView ที่ได้รับการปรับปรุงและ SafeAreaEdges บทความนี้จะพาผู้อ่านไปสร้างแอปพลิเคชัน cross-platform สำรวจสถาปัตยกรรมเบื้องหลัง MAUI และตอบคำถามสัมภาษณ์งานที่ผู้จ้างงานถามในปี 2026

.NET MAUI 10 LTS

.NET 10 เป็นเวอร์ชัน Long-Term Support (สนับสนุนจนถึงพฤศจิกายน 2028) MAUI 10 เน้นที่คุณภาพและประสิทธิภาพมากกว่า UI control ใหม่ — ทำให้เป็นเวอร์ชัน MAUI ที่เสถียรที่สุดจนถึงปัจจุบัน ตอนนี้มาในรูปแบบ .NET workload และแพ็กเกจ NuGet ทำให้สามารถกำหนดเวอร์ชันเฉพาะต่อโปรเจกต์ได้

การตั้งค่าโปรเจกต์ .NET MAUI 10 ตั้งแต่เริ่มต้น

วิธีที่เร็วที่สุดในการมีแอป MAUI ที่ทำงานได้เริ่มต้นจาก .NET CLI .NET 10 แนะนำ template โปรเจกต์ใหม่ที่รวม service defaults ของ .NET Aspire เชื่อมต่อ telemetry และ service discovery ตั้งแต่แรก

bash
# ติดตั้ง workload MAUI (หากยังไม่ได้ติดตั้ง)
dotnet workload install maui

# สร้างแอป MAUI ใหม่
dotnet new maui -n CrossPlatformDemo
cd CrossPlatformDemo

# รันบน Android emulator
dotnet build -t:Run -f net10.0-android

โครงสร้าง single-project รวมโค้ดเฉพาะแพลตฟอร์มไว้ใต้โฟลเดอร์ Platforms/ ในขณะที่แชร์ส่วนที่เหลือ ไฟล์ MauiProgram.cs ทำหน้าที่เป็น composition root — เป็นที่ลงทะเบียน service, font และ handler

MauiProgram.cscsharp
using Microsoft.Extensions.Logging;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            });

        // ลงทะเบียน service สำหรับ dependency injection
        builder.Services.AddSingleton<IApiService, ApiService>();
        builder.Services.AddTransient<MainViewModel>();

#if DEBUG
        builder.Logging.AddDebug();
#endif

        return builder.Build();
    }
}

Dependency injection ใน MAUI ใช้รูปแบบเดียวกันกับ ASP.NET Core Service แบบ Singleton คงอยู่ตลอดอายุของแอป Service แบบ Transient ถูกสร้างใหม่ทุกครั้งที่มีการร้องขอ และ Service แบบ Scoped — แม้จะใช้ได้ — ต้องระมัดระวังเนื่องจาก MAUI ไม่มีแนวคิด scope ในตัวเหมือน HTTP request

Handler: สถาปัตยกรรมเบื้องหลังการ Render Cross-Platform

MAUI แทนที่ renderer ของ Xamarin.Forms ด้วยสถาปัตยกรรม handler Handler ทำหน้าที่แมป control cross-platform แต่ละตัวไปยังคู่ native ผ่านชั้น abstraction ที่บาง ความแตกต่างสำคัญ: handler เป็น stateless และแยกออกจาก virtual view ทำให้เร็วกว่าและง่ายต่อการปรับแต่ง

CustomEntryHandler.cs — ปรับแต่ง control Entry บน Androidcsharp
using Microsoft.Maui.Handlers;

public class CustomEntryHandler : EntryHandler
{
    protected override void ConnectHandler(MauiAppCompatEditText platformView)
    {
        base.ConnectHandler(platformView);
        // ลบเส้นใต้เริ่มต้นบน Android
        platformView.SetBackgroundColor(Android.Graphics.Color.Transparent);
    }
}

// ลงทะเบียนใน MauiProgram.cs
builder.ConfigureMauiHandlers(handlers =>
{
    handlers.AddHandler<Entry, CustomEntryHandler>();
});

ใน .NET 10 control Entry และ Editor บน Android เปลี่ยนจาก AppCompatEditText เป็น MauiAppCompatEditText เพิ่มการรองรับ native สำหรับ event SelectionChanged Handler ของ CollectionView และ CarouselView ที่ปรับปรุงใน .NET 9 กลายเป็นค่าเริ่มต้นบน iOS และ Mac Catalyst แก้ไขปัญหาความเสถียรที่มีมานาน

MVVM ด้วย CommunityToolkit.Mvvm: กำจัด Boilerplate

Source generator ของ CommunityToolkit.Mvvm ลดโค้ดซ้ำซ้อนของ MVVM ได้ราว 80% ไม่ต้องเขียน INotifyPropertyChanged เอง ไม่ต้องมี command wrapper — attribute เป็นตัวขับเคลื่อน code generation

MainViewModel.cscsharp
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

public partial class MainViewModel : ObservableObject
{
    private readonly IApiService _apiService;

    public MainViewModel(IApiService apiService)
    {
        _apiService = apiService;
    }

    // Source generator สร้าง property 'Title' พร้อม change notification
    [ObservableProperty]
    private string _title = string.Empty;

    // Source generator สร้าง async command พร้อมรองรับ cancellation
    [RelayCommand]
    private async Task LoadDataAsync(CancellationToken ct)
    {
        var data = await _apiService.FetchAsync(ct);
        Title = data.Title;
    }
}

XAML ทำ binding โดยตรงกับ property และ command ที่ถูกสร้างขึ้น:

xml
<!-- MainPage.xaml -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:CrossPlatformDemo.ViewModels"
             x:DataType="vm:MainViewModel">
    <VerticalStackLayout Padding="20" Spacing="16">
        <Label Text="{Binding Title}"
               FontSize="24"
               HorizontalOptions="Center" />
        <Button Text="Load Data"
                Command="{Binding LoadDataCommand}"
                IsEnabled="{Binding IsLoading, Converter={StaticResource InverseBoolConverter}}" />
        <ActivityIndicator IsRunning="{Binding IsLoading}"
                           IsVisible="{Binding IsLoading}" />
    </VerticalStackLayout>
</ContentPage>

Attribute x:DataType เปิดใช้งาน compiled bindings ซึ่งเร็วกว่า binding แบบ reflection และแสดง error ตอน compile-time เมื่อ binding path ผิด

พร้อมที่จะพิชิตการสัมภาษณ์ .NET แล้วหรือยังครับ?

ฝึกฝนด้วยตัวจำลองแบบโต้ตอบ, flashcards และแบบทดสอบเทคนิคครับ

HybridWebView ใน .NET 10: เชื่อมต่อ Native กับ Web

HybridWebView ช่วยให้สามารถฝังเนื้อหา web ภายในแอป MAUI พร้อมรักษาการสื่อสารสองทางระหว่าง C# และ JavaScript .NET 10 เพิ่มความสามารถสามอย่าง: การเรียก JavaScript แบบ fire-and-forget, event สำหรับการเริ่มต้นเพื่อกำหนดค่าเฉพาะแพลตฟอร์ม และการดักจับ web request

MainPage.xaml.cs — การโต้ตอบกับ HybridWebViewcsharp
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        // Event เริ่มต้นสำหรับการตั้งค่าเฉพาะแพลตฟอร์ม
        hybridWebView.WebViewInitialized += (sender, args) =>
        {
            // เข้าถึง native platform view หลังจากเริ่มต้น
            System.Diagnostics.Debug.WriteLine("WebView ready");
        };
    }

    // เรียก JavaScript จาก C#
    private async void OnCallJsClicked(object sender, EventArgs e)
    {
        var result = await hybridWebView.InvokeJavaScriptAsync<string>(
            "getFormData",  // ชื่อฟังก์ชัน JS
            HybridSampleContext.Default.String  // บริบท serialization JSON
        );
        await DisplayAlert("Result", result, "OK");
    }

    // Fire-and-forget: ไม่ต้องการ return type (.NET 10)
    private async void OnResetClicked(object sender, EventArgs e)
    {
        await hybridWebView.InvokeJavaScriptAsync("resetForm");
    }
}

JavaScript ที่เกี่ยวข้องรับการเรียกและสามารถส่งข้อความกลับไปยัง C#:

wwwroot/index.html (เนื้อหา HybridWebView)javascript
function getFormData() {
    return JSON.stringify({
        name: document.getElementById('name').value,
        email: document.getElementById('email').value
    });
}

function resetForm() {
    document.getElementById('name').value = '';
    document.getElementById('email').value = '';
}

Exception ของ JavaScript ที่เกิดขึ้นระหว่าง InvokeJavaScriptAsync ตอนนี้ถูกส่งต่อไปยัง .NET โดยอัตโนมัติเป็น exception ขจัดความล้มเหลวที่ตรวจไม่พบ

SafeAreaEdges: Layout ที่สมบูรณ์แบบบนทุกอุปกรณ์

.NET MAUI 10 แนะนำ property SafeAreaEdges บน Layout, ContentView, ContentPage, Border และ ScrollView Enum ใหม่ (None, SoftInput, Container, Default, All) แทนที่ Page.UseSafeArea เดิมที่เฉพาะ iOS ด้วยแนวทาง cross-platform

xml
<!-- การควบคุม safe area แบบละเอียดต่อส่วน -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             SafeAreaEdges="All">
    <Grid RowDefinitions="Auto,*,Auto">
        <!-- Header เคารพ safe area ทั้งหมด -->
        <Border Grid.Row="0" SafeAreaEdges="Container">
            <Label Text="Header" />
        </Border>

        <!-- เนื้อหาเลื่อนใต้ safe area -->
        <ScrollView Grid.Row="1" SafeAreaEdges="SoftInput">
            <VerticalStackLayout Padding="16">
                <Entry Placeholder="พิมพ์ที่นี่..." />
            </VerticalStackLayout>
        </ScrollView>

        <!-- Footer หลีกเลี่ยง home indicator -->
        <Border Grid.Row="2" SafeAreaEdges="Container">
            <Label Text="Footer" />
        </Border>
    </Grid>
</ContentPage>

SoftInput ปรับเนื้อหาเมื่อแป้นพิมพ์บนหน้าจอปรากฏ Container หลีกเลี่ยง notch, sensor housing และ home indicator ค่าเหล่านี้สามารถรวมกันได้ต่อ control ทำให้ header อยู่ใต้ status bar ในขณะที่พื้นที่เนื้อหายังคงเว้นระยะ

การย้ายจาก Xamarin.Forms ไปยัง .NET MAUI

Xamarin.Forms สิ้นสุดการสนับสนุนในเดือนพฤษภาคม 2024 การย้ายไปยัง MAUI เกี่ยวข้องกับการเปลี่ยนแปลงโครงสร้างที่มากกว่าการเปลี่ยน namespace ต่อไปนี้เป็นรายการตรวจสอบการย้ายที่อ้างอิงจากประสบการณ์แปลงโปรเจกต์จริง:

Xamarin EOL

Xamarin.Forms ไม่ได้รับการสนับสนุนตั้งแต่เดือนพฤษภาคม 2024 แอปพลิเคชันที่ยังทำงานบน Xamarin มีความเสี่ยงด้านความปลอดภัยและความเข้ากันได้ .NET MAUI 10 (LTS, สนับสนุนจนถึงพฤศจิกายน 2028) คือเป้าหมายการย้ายที่กำหนดไว้

  1. โครงสร้างโปรเจกต์ — แปลงจากโปรเจกต์เฉพาะแพลตฟอร์มเป็นโมเดล single-project ของ MAUI ย้ายโค้ดที่ใช้ร่วมกันไปที่ root โค้ดแพลตฟอร์มไปที่ Platforms/
  2. Namespace — แทนที่ Xamarin.Forms ด้วย Microsoft.Maui.Controls และ Xamarin.Essentials ด้วย Microsoft.Maui.Essentials (ตอนนี้ built-in ใน MAUI)
  3. Renderer เป็น Handler — Custom renderer ต้องเขียนใหม่เป็น handler API ของ handler ง่ายกว่าแต่ logic การแมปต่างกัน
  4. Startup — แทนที่การเริ่มต้น App.xaml.cs ด้วย MauiProgram.cs โดยใช้ builder pattern
  5. แพ็กเกจ NuGet — แพ็กเกจยุค Xamarin จำนวนมากมีเวอร์ชัน MAUI ตรวจสอบความเข้ากันได้ก่อนอัปเกรด
  6. Dependency injection — MAUI ใช้ Microsoft.Extensions.DependencyInjection โดย native แทนที่ DI container ของบุคคลที่สามหรือการเรียก DependencyService

.NET Upgrade Assistant ทำขั้นตอนที่ 1-2 บางส่วนโดยอัตโนมัติ แต่ handler (ขั้นตอนที่ 3) และการปรับ business logic ต้องทำด้วยตนเอง

คำถามสัมภาษณ์งาน .NET MAUI ยอดนิยมสำหรับปี 2026

คำถามเหล่านี้สะท้อนสิ่งที่ทีมรับสมัครถามในปี 2026 อ้างอิงจากระบบนิเวศ .NET 10 ปัจจุบัน

สถาปัตยกรรม handler ของ MAUI แตกต่างจาก renderer ของ Xamarin.Forms อย่างไร?

Renderer ใน Xamarin.Forms มี coupling ที่แน่นหนากับทั้ง control cross-platform และ native view สร้างการพึ่งพาแบบสองทิศทาง Handler ใน MAUI เป็น mapper แบบ stateless: รับการแจ้งเตือนเมื่อ property เปลี่ยนแปลงและนำไปใช้กับ native view ผ่าน dictionary ของ mapper การแยกส่วนนี้ทำให้ handler ทดสอบ ขยาย และนำกลับมาใช้ใหม่ได้ง่ายกว่า Dictionary PropertyMapper และ CommandMapper แทนที่รูปแบบ override OnElementPropertyChanged ทำให้การปรับแต่งชัดเจนแทนที่จะซ่อนอยู่ใน switch statement

ข้อผิดพลาดด้าน DI lifetime ที่เฉพาะสำหรับ MAUI มีอะไรบ้าง?

MAUI รองรับ lifetime แบบ Singleton, Transient และ Scoped แต่ Scoped ทำงานต่างจาก ASP.NET Core ไม่มีขอบเขต scope ตามธรรมชาติ (เหมือน HTTP request) Service แบบ Scoped ที่ลงทะเบียนใน MAUI ทำงานเหมือน Singleton เว้นแต่จะสร้าง scope แบบกำหนดเองด้วยตนเอง ข้อผิดพลาดที่พบบ่อย: ลงทะเบียน ViewModel เป็น Singleton เมื่อมันเก็บ state เฉพาะหน้า (ข้อมูลเก่าเมื่อนำทาง) หรือลงทะเบียน database connection เป็น Transient (connection pool หมด) กฎทั่วไป: ViewModel เป็น Transient, service เป็น Singleton และหลีกเลี่ยง Scoped เว้นแต่ lifecycle ของ scope จะถูกจัดการอย่างชัดเจน

เคล็ดลับสัมภาษณ์

เมื่อตอบคำถามเกี่ยวกับ DI ให้แสดงความเข้าใจว่า lifecycle ของ MAUI แตกต่างจากโมเดล request-scoped ของ ASP.NET Core อย่างไร ผู้สัมภาษณ์มองหาความตระหนักเกี่ยวกับ memory leak และปัญหา state เก่าที่เฉพาะสำหรับแอปมือถือที่ทำงานนาน

Compiled binding แตกต่างจาก binding แบบ reflection ใน MAUI อย่างไร?

Binding แบบ reflection แก้ไข property path ตอน runtime โดยใช้ System.Reflection ซึ่งช้าและสร้าง error ตอน runtime สำหรับการพิมพ์ผิด Compiled binding ที่เปิดใช้งานผ่าน x:DataType แก้ไข binding path ตอน compile time Compiler สร้างโค้ดเข้าถึง property โดยตรง ข้าม reflection ทั้งหมด สิ่งนี้ปรับปรุงเวลาเริ่มต้น ลดการจัดสรรหน่วยความจำ และจับ error ของ binding ตอน build ใน .NET 10 source generator XAML ใหม่เพิ่มประสิทธิภาพอีกโดยคอมไพล์ XAML ตอน build time แทนที่จะ parse ตอน runtime

มีกลยุทธ์อะไรบ้างสำหรับการแชร์โค้ดระหว่างแอป MAUI และ backend ASP.NET Core?

แนวทางที่แนะนำใช้ shared class library ที่มี DTO, logic ตรวจสอบ และ business rules ทั้งแอป MAUI และ backend ASP.NET Core อ้างอิง library นี้ .NET 10 เสริมรูปแบบนี้ด้วยการรวม .NET Aspire สำหรับ MAUI ที่ให้ service discovery และ telemetry ข้ามโปรเจกต์มือถือและ backend Shared contract ที่ใช้ source generator ของ System.Text.Json รับประกันความสอดคล้องของ serialization ข้อจำกัดหลัก: shared library ต้อง target net10.0 (ไม่ใช่ TFM เฉพาะแพลตฟอร์ม) เพื่อรักษาความ portable

HybridWebView แตกต่างจาก BlazorWebView ใน MAUI อย่างไร?

BlazorWebView โฮสต์แอปพลิเคชัน Blazor เต็มรูปแบบภายในแอป MAUI Component ของ Razor เรนเดอร์ลงใน WebView ที่ฝังไว้ แต่ .NET runtime ทำงานแบบ native (ไม่ผ่าน WebAssembly) HybridWebView เบากว่า: โหลดเนื้อหา HTML/CSS/JS แบบ static และให้ interop C#-ไป-JavaScript โดยไม่มี overhead ของ framework Blazor ทางเลือกขึ้นอยู่กับ use case BlazorWebView เหมาะสำหรับทีมที่มี component Blazor อยู่แล้วและต้องการ code reuse HybridWebView เหมาะสำหรับสถานการณ์ที่เนื้อหา web ที่มีอยู่ (dashboard, แผนที่, editor) ต้องการการรวมแบบ native โดยไม่ต้องใช้ framework เต็มรูปแบบ

ฝึกฝนเพิ่มเติมด้วยคำถามสัมภาษณ์ .NET บน SharpSkill เพื่อเสริมความเข้าใจแนวคิดเหล่านี้ด้วยแบบฝึกหัดแบบโต้ตอบ

เริ่มฝึกซ้อมเลย!

ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ

สรุป

  • .NET MAUI 10 เป็นเวอร์ชัน LTS (สนับสนุนถึงพฤศจิกายน 2028) ที่เน้นความเสถียรและประสิทธิภาพ — เป็นตัวเลือกที่เชื่อถือได้สำหรับแอป cross-platform ระดับ production
  • สถาปัตยกรรม handler แทนที่ renderer ของ Xamarin ด้วย mapper แบบ stateless ปรับปรุงความสามารถในการทดสอบและปรับแต่งผ่าน PropertyMapper และ CommandMapper
  • Source generator ของ CommunityToolkit.Mvvm ลด boilerplate MVVM ส่วนใหญ่ — attribute [ObservableProperty] และ [RelayCommand] แทนที่การ implement INotifyPropertyChanged และ command แบบ manual
  • HybridWebView ใน .NET 10 เพิ่มการเรียก JavaScript แบบ fire-and-forget, event เริ่มต้น และการดักจับ request สำหรับการรวม native-web
  • SafeAreaEdges ให้การควบคุมแบบละเอียด cross-platform สำหรับ device cutout, แป้นพิมพ์ และ system bar แทนที่ UseSafeArea เดิมที่เฉพาะ iOS
  • การย้าย Xamarin.Forms ต้องเขียน handler ใหม่และ refactor startup — .NET Upgrade Assistant จัดการเปลี่ยน namespace แต่งาน manual ยังจำเป็นสำหรับ custom renderer
  • การเตรียมตัวสัมภาษณ์ควรเน้นที่สถาปัตยกรรม handler vs. renderer, ข้อผิดพลาด DI lifetime ในแอปที่ทำงานนาน, compiled binding และข้อแลกเปลี่ยนระหว่าง HybridWebView vs. BlazorWebView

เริ่มฝึกซ้อมเลย!

ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ

แท็ก

#dotnet
#maui
#cross-platform
#mobile
#interview

แชร์

บทความที่เกี่ยวข้อง