微軟開發



Visual Studio

開發環境簡介

Visual Studio 是由微軟開發的一個整合式開發環境(IDE),支援多種程式語言如 C++、C#、VB.NET、Python、JavaScript 等。適用於開發桌面應用程式、網站、雲端服務及行動應用程式。

主要功能

版本區別

平台支援

Visual Studio 支援 Windows 作業系統,另有 Visual Studio for Mac,專為 macOS 設計。

常見用途



Visual Studio 的語法格式化

1. 自動格式化代碼

Visual Studio 提供快捷鍵來快速格式化代碼,適用於各種編程語言: - 使用快捷鍵 `Ctrl + K, Ctrl + D` 格式化整個檔案。 - 使用快捷鍵 `Ctrl + K, Ctrl + F` 格式化選中的代碼區塊。

2. 啟用自動格式化

Visual Studio 支援在檔案儲存時自動格式化代碼: 1. 點擊 **工具 > 選項**。 2. 前往 **文字編輯器 > [語言] > 編碼樣式 > 常規**。 3. 勾選 **在檔案儲存時重新格式化代碼**。

3. 修改格式化設定

1. 打開 **工具 > 選項**。 2. 前往 **文字編輯器 > [語言] > 編碼樣式 > 格式化**。 3. 在此可以調整縮排、括號樣式、空白行等詳細格式化設定。

4. 使用編碼樣式設定檔

Visual Studio 支援編碼樣式設定檔(.editorconfig)來統一團隊的代碼風格: 1. 在專案的根目錄新增一個 `.editorconfig` 檔案。 2. 定義格式規則,例如:
   [*.cs]
   indent_style = space
   indent_size = 4
   
3. 檔案儲存後,格式化會自動遵循這些規則。

5. 安裝擴展工具

如果內建格式化功能無法滿足需求,可以安裝擴展工具: - 在 **擴展管理員** 中搜尋並安裝工具,例如 **CodeMaid** 或 **ReSharper**。 - 這些工具提供更多代碼格式化與重構選項。

6. 快速修正格式問題

當格式問題出現時,可以使用快速修正功能: - 在問題代碼上點擊右鍵,選擇 **快速動作與重構**。 - 選擇 **格式化文件** 或 **格式化選區**。

7. 總結

- 使用快捷鍵快速格式化代碼。 - 啟用檔案儲存時自動格式化功能。 - 使用 `.editorconfig` 統一代碼風格。 - 安裝擴展工具提升格式化能力。 - 善用快速修正功能改善代碼可讀性。

.NET SDK 版本

檢查已安裝的 .NET SDK

您可以透過命令列工具檢查電腦上安裝的 .NET SDK 版本:

dotnet --list-sdks

若出現類似下列結果,表示已安裝的 SDK 版本:

8.0.100 [C:\Program Files\dotnet\sdk]
9.0.100-preview.3.24172.9 [C:\Program Files\dotnet\sdk]

如果未出現您想使用的版本,表示該版本尚未安裝。

下載與安裝 .NET SDK

  1. 前往 .NET 官方下載頁面
  2. 選擇對應版本(例如 .NET 9)與作業系統平台(Windows、macOS、Linux)
  3. 下載並執行安裝程式

在 Visual Studio 中開啟命令提示字元

  1. 開啟 Visual Studio
  2. 選單列點選:工具 > 命令列 > 開發人員命令提示字元
  3. 將會開啟一個已設定好開發環境路徑的命令提示字元視窗,可直接使用 dotnet 命令

若未看到此選項,您也可以使用 Windows 的開始選單搜尋「Developer Command Prompt for VS」開啟。

使用 Visual Studio 的內建終端機(2022 起支援)

  1. 在 Visual Studio 中點選:檢視 > 終端機 或使用快速鍵 Ctrl + `
  2. 選擇終端機類型(例如 PowerShell 或 CMD)
  3. 可直接輸入 dotnet 命令檢查或操作 SDK


C# 語言

語言特色

基本範例

using System;

class Program {
    static void Main() {
        string name = "世界";
        Console.WriteLine($"哈囉, {name}!");
    }
}

常見應用領域

進階功能



CS8618 非Nullable未初始化

警告內容

CS8618 意思是:在建構函式結束時,非 Nullable 的屬性沒有被初始化,因此 C# 編譯器警告它可能會是 null

範例問題

public class Product {
    public string Name { get; set; }  // 警告 CS8618
}

解決方式

方法一:在建構函式中賦值(推薦)

public class Product {
    public string Name { get; set; }

    public Product(string name) {
        Name = name;
    }
}

方法二:給屬性預設值

public class Product {
    public string Name { get; set; } = string.Empty;
}

方法三:允許 Null

public class Product {
    public string? Name { get; set; }
}

→ 適用於 Name 合理允許為 null 的情況。

方法四:使用 required 修飾元(C# 11+ 支援)

public class Product {
    public required string Name { get; set; }
}

// 呼叫端必須初始化
var p = new Product { Name = "手機" }; // OK

建議



.NET 程式

將 float 轉成字串避免科學記號

問題說明

在 C++/CLI 中,如果直接用 floatSystem::String 相加,例如:

System::String^ tmpStr = "Value: " + someFloat;
someFloat 很大或很小時,可能會自動以科學記號(e.g. 1.23E+05)顯示。

解決方式

可用 System::String::FormatToString 搭配格式字串,指定小數位數並避免科學記號。

範例程式


using namespace System;

float value = 123456.789f;

// 方法1:String::Format
String^ tmpStr1 = String::Format("Value: {0:F2}", value); // F2 表示小數點後 2 位
Console::WriteLine(tmpStr1);

// 方法2:ToString 搭配格式
String^ tmpStr2 = "Value: " + value.ToString("F2");
Console::WriteLine(tmpStr2);

// 方法3:更多位數
String^ tmpStr3 = "Value: " + value.ToString("F6");
Console::WriteLine(tmpStr3);

格式化代碼說明



使用 .NET C++ 取得目錄中最新的檔案

簡介

在 .NET C++ 中,可以使用 System::IO 命名空間提供的功能來操作檔案與目錄。 取得目錄中最新的檔案,可以透過讀取所有檔案資訊並比較最後修改日期實現。

範例程式碼

以下是一個完整的範例,展示如何取得指定目錄中最新的檔案:

#include "stdafx.h"
#include <iostream>
#include <cliext/vector>
#include <System.IO>

using namespace System;
using namespace System::IO;
using namespace cliext;

int main()
{
    try
    {
        // 指定目錄路徑
        String^ directoryPath = "C:\\Your\\Directory\\Path";

        // 檢查目錄是否存在
        if (!Directory::Exists(directoryPath))
        {
            Console::WriteLine("目錄不存在: {0}", directoryPath);
            return -1;
        }

        // 取得目錄中的所有檔案
        array^ files = Directory::GetFiles(directoryPath);

        // 如果目錄中沒有檔案
        if (files->Length == 0)
        {
            Console::WriteLine("目錄中沒有檔案。");
            return 0;
        }

        // 找到最新的檔案
        String^ newestFile = nullptr;
        DateTime newestTime = DateTime::MinValue;

        for each (String^ file in files)
        {
            // 取得檔案的最後修改時間
            DateTime lastWriteTime = File::GetLastWriteTime(file);

            // 比較時間並更新最新檔案資訊
            if (lastWriteTime > newestTime)
            {
                newestTime = lastWriteTime;
                newestFile = file;
            }
        }

        // 輸出最新檔案資訊
        Console::WriteLine("最新檔案: {0}", newestFile);
        Console::WriteLine("最後修改時間: {0}", newestTime);
    }
    catch (Exception^ ex)
    {
        Console::WriteLine("發生錯誤: {0}", ex->Message);
    }

    return 0;
}

程式碼解說

應用場景

注意事項



.NET: System.Reflection

1. System.Reflection 是什麼?

System.Reflection 是 .NET 框架中的一個命名空間,提供了檢查和操作元數據的工具,使開發者可以在運行時動態檢查類型、方法、屬性等,並動態創建和操縱對象。

2. System.Reflection 的用途

3. 常見的 System.Reflection 類別

4. 使用範例

以下是一個使用 System.Reflection 的範例程式,展示如何動態檢查類型和方法,並調用方法。


// 定義一個簡單的範例類別
public class SampleClass {
    public string SayHello(string name) {
        return $"Hello, {name}!";
    }
}

// 使用 Reflection 來動態調用方法
using System;
using System.Reflection;

class Program {
    static void Main() {
        // 創建 SampleClass 類別的實例
        Type sampleType = typeof(SampleClass);
        object sampleInstance = Activator.CreateInstance(sampleType);

        // 獲取 SayHello 方法資訊
        MethodInfo methodInfo = sampleType.GetMethod("SayHello");

        // 動態調用 SayHello 方法
        object result = methodInfo.Invoke(sampleInstance, new object[] { "World" });
        Console.WriteLine(result); // 輸出: Hello, World!
    }
}
        

在上述範例中,我們使用 Activator.CreateInstance 來創建類別的實例,並使用 MethodInfo.Invoke 來調用方法 SayHello

5. 常見應用場景



System::Management::ManagementClass

用途

System::Management::ManagementClass 是 .NET Framework 中提供用於操作 Windows Management Instrumentation (WMI) 的類別之一。它允許開發者讀取、操作和管理系統資訊,例如硬體、作業系統、網路設定等。

命名空間

System::Management 是位於 System.Management.dll 中的命名空間,使用此功能需先加入參考。

常見用途

簡單範例

// C++/CLI 寫法
using namespace System;
using namespace System::Management;

int main() {
    try {
        ManagementClass^ mc = gcnew ManagementClass("Win32_OperatingSystem");
        for each (ManagementObject^ mo in mc->GetInstances()) {
            Console::WriteLine("OS 名稱: {0}", mo["Caption"]);
        }
    }
    catch (Exception^ ex) {
        Console::WriteLine("錯誤: {0}", ex->Message);
    }
    return 0;
}

常見錯誤與排除

相關類別



修復 Win32_NetworkAdapterConfiguration 發生 Invalid class 錯誤

錯誤代碼說明

當使用 `System::Management::ManagementClass("Win32_NetworkAdapterConfiguration")` 時出現錯誤代碼 `0x80041010`,表示 WMI 無法找到該類別,這通常代表:

解決步驟

以下為完整修復方式,可重新建立 WMI 儲存庫,適用於 Windows 10/11:
net stop winmgmt
winmgmt /resetrepository
net start winmgmt

說明

修復後驗證

可使用下列任一方式確認是否修復成功: 方式一:PowerShell 查詢
Get-WmiObject Win32_NetworkAdapterConfiguration
方式二:WMI 測試工具 (wbemtest)
  1. 按 Win + R,輸入 wbemtest
  2. 點選「Connect」,輸入 root\cimv2 並連線
  3. 點選「Query」,輸入 SELECT * FROM Win32_NetworkAdapterConfiguration

補充建議



.NET 程式在 Chromebook 上執行方法

1. 使用 Chromebook 的 Linux 支援執行 .NET

大多數現代 Chromebook 支援透過 Crostini 專案來運行 Linux 應用程式。

  1. 啟用 Linux 功能:
  2. 安裝 .NET SDK:
  3. 在終端機中編譯並執行 .NET 應用程式。

2. 使用雲端開發環境

無需在本地安裝任何軟體,即可在 Chromebook 上使用雲端平台運行 .NET 程式。

3. 使用 Docker 容器運行 .NET

Chromebook 支援使用容器運行應用程式,您可以透過 Docker 啟動 .NET 環境。

  1. 在 Linux 環境中安裝 Docker。
  2. 下載 .NET 容器映像檔:
    docker pull mcr.microsoft.com/dotnet/runtime:7.0
  3. 在容器內運行您的 .NET 程式。

4. 使用跨平台支援功能

從 .NET 6 開始,應用程式可以跨多平台運行,包括 Linux。將您的應用程式編譯為跨平台格式並部署至 Chromebook。

  1. 在任何機器上編譯您的應用程式:
    dotnet publish -c Release -r linux-x64 --self-contained
  2. 將編譯好的檔案傳輸到 Chromebook,使用附帶的運行時執行。

注意事項



.NET UI 程式設計

主要技術

簡單 WinForms 範例

using System;
using System.Windows.Forms;

public class MyForm : Form {
    public MyForm() {
        Button btn = new Button();
        btn.Text = "點我";
        btn.Click += (s, e) => MessageBox.Show("你點了按鈕!");
        Controls.Add(btn);
    }

    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.Run(new MyForm());
    }
}

簡單 WPF 範例 (XAML + C#)

// MainWindow.xaml
<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        Title="WPF 範例" Height="200" Width="300">
    <StackPanel>
        <Button Content="點我" Click="Button_Click"/>
    </StackPanel>
</Window>

// MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e) {
    MessageBox.Show("你點了按鈕!");
}

簡單 MAUI 範例

// MainPage.xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             x:Class="MyApp.MainPage">
    <VerticalStackLayout Spacing="25" Padding="30">
        <Button Text="點我" Clicked="OnButtonClicked"/>
    </VerticalStackLayout>
</ContentPage>

// MainPage.xaml.cs
private void OnButtonClicked(object sender, EventArgs e) {
    await DisplayAlert("通知", "你點了按鈕!", "OK");
}

UI 技術選擇建議

技術 用途 平台
WinForms 快速開發桌面應用 Windows
WPF 複雜桌面應用、MVVM 模式 Windows
MAUI 跨平台應用 Windows、macOS、Android、iOS
Blazor Web 前端開發 跨平台(Web)


.NET 遍歷子控制項以批量修改屬性

以下範例展示了如何使用 Controls->GetEnumerator() 方法來逐一遍歷 .NET 表單中的所有子控制項並批量修改其屬性。

範例程式碼:


using System;
using System.Drawing;
using System.Windows.Forms;

public class FormExample : Form
{
    public FormExample()
    {
        // 初始化一些控制項
        Button button1 = new Button { Text = "Button 1", Location = new Point(10, 10) };
        TextBox textBox1 = new TextBox { Location = new Point(10, 50) };
        
        Controls.Add(button1);
        Controls.Add(textBox1);

        // 使用 GetEnumerator() 遍歷並修改控制項屬性
        ModifyControls();
    }

    private void ModifyControls()
    {
        var enumerator = Controls.GetEnumerator();
        
        while (enumerator.MoveNext())
        {
            Control control = (Control)enumerator.Current;

            // 設定範例:將所有控制項的背景色設為淺藍
            control.BackColor = Color.LightBlue;
            
            // 若控制項為 TextBox,將其設為不可編輯
            if (control is TextBox)
            {
                control.Enabled = false;
            }
        }
    }
    
    // 啟動應用程式
    public static void Main()
    {
        Application.Run(new FormExample());
    }
}

說明

**GetEnumerator()**: 利用 `Controls.GetEnumerator()` 方法來取得控制項的列舉器,這樣可以遍歷所有子控制項。

**條件修改**: 在 `while` 迴圈中,對每個 `Control` 物件進行屬性修改,例如將背景色設為淺藍,並根據控制項類型進行特定修改,如將 `TextBox` 設為不可編輯。

**用途**: 這種方法在需要批量修改屬性時非常有效,比如調整 UI 風格或在特定情況下禁用多個控制項。

執行效果

執行後,所有控制項的背景色會變成淺藍色,且所有 `TextBox` 控制項將被設為不可編輯。



.NET StackTrace中取得 Message m 的內容

問題背景

當堆疊追蹤中出現以下錯誤訊息時,開發者可能需要檢查 Message 物件的內容:

   at ....MainForm.Dispose(Boolean A_0)
   at System.Windows.Forms.Form.WmClose(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   ...
    

此時需要透過覆寫或檢測 WndProc 方法中的 Message m 來檢查其詳細資訊。

解決方法

以下提供幾種方法來檢查或記錄 Message 物件的內容。

1. 覆寫 WndProc 方法

如果可以存取表單或控制項的原始碼,建議覆寫 WndProc 方法,直接記錄或檢查 Message m 的內容。


protected override void WndProc(ref Message m)
{
    try
    {
        // 記錄 Message 的內容
        Console.WriteLine($"Message Details: hWnd={m.HWnd}, Msg={m.Msg}, WParam={m.WParam}, LParam={m.LParam}");
        base.WndProc(ref m);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Exception: {ex}");
        throw; // 保持原有例外行為
    }
}

    

這段程式碼會在每次接收到訊息時記錄相關資訊,並允許開發者進一步分析。

2. 在 Dispose 方法中加入例外處理

如果錯誤發生在 Dispose 方法中,可以在方法內加入例外處理來檢查相關資訊。


protected override void Dispose(bool disposing)
{
    try
    {
        if (disposing)
        {
            // 釋放資源
        }
        base.Dispose(disposing);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Exception in Dispose: {ex}");
        throw;
    }
}

    

這樣可以確保在釋放資源時不會忽略重要的錯誤資訊。

3. 使用全域例外處理

如果無法確定錯誤發生的位置,可以透過全域例外處理來記錄堆疊追蹤和相關資訊。


AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
{
    Exception ex = (Exception)args.ExceptionObject;
    Console.WriteLine($"Unhandled Exception: {ex}");
    Environment.Exit(1);
};

    

4. 使用 Debug 工具檢查 Message

可以使用 Visual Studio 將斷點設置在 WndProcDispose 方法中,並檢查 Message 物件的內容。

Message 物件的關鍵屬性

注意事項



覆寫 Form.WmClose(Message& m) 在 .NET C++

問題背景

在 .NET C++/CLI 中,WmClose(Message& m)System.Windows.Forms.Form 的內部保護方法,無法直接覆寫。不過,可以透過覆寫 WndProc 方法來攔截並處理 WM_CLOSE 訊息,以達到類似覆寫 WmClose 的效果。

完整範例


#include <Windows.h>
#include <System.Windows.Forms.h>

using namespace System;
using namespace System::Windows::Forms;

public ref class CustomForm : public Form
{
protected:
    // 模擬 WmClose 行為的覆寫
    void WmClose(Message% m)
    {
        // 在這裡加入自定義的 WM_CLOSE 行為
        if (MessageBox::Show("確定要關閉視窗嗎?", "確認", MessageBoxButtons::YesNo) == DialogResult::Yes)
        {
            // 繼續調用基底行為以進行正常關閉
            this->Form::WndProc(m);
        }
        else
        {
            // 阻止關閉視窗
            return;
        }
    }

    // 覆寫 WndProc,攔截 WM_CLOSE 訊息並調用 WmClose
    virtual void WndProc(Message% m) override
    {
        const int WM_CLOSE = 0x0010;

        if (m.Msg == WM_CLOSE)
        {
            WmClose(m); // 調用自定義的 WmClose 方法
        }
        else
        {
            // 處理其他訊息
            Form::WndProc(m);
        }
    }
};

[STAThread]
int main(array<String^>^ args)
{
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false);

    CustomForm^ form = gcnew CustomForm();
    form->Text = "覆寫 WmClose 行為範例";
    Application::Run(form);

    return 0;
}

    

程式碼解釋

1. WmClose 方法

模擬覆寫 WmClose 方法,在這裡自定義視窗關閉的行為。透過確認對話框詢問使用者是否要關閉視窗。

2. 覆寫 WndProc

覆寫 WndProc 方法來攔截 WM_CLOSE 訊息,並將其委派給自定義的 WmClose 方法。

3. 繼續處理其他訊息

在沒有攔截 WM_CLOSE 的情況下,調用基底類別的 WndProc 方法處理其他訊息。

注意事項



System::Windows::Forms::Control::InvokeRequired

用途說明

InvokeRequiredSystem::Windows::Forms::Control 的屬性,用來判斷目前執行緒是否為控制項所屬的 UI 執行緒。當從背景執行緒存取 UI 控件時,應使用 Invoke 將操作封送回 UI 執行緒。

完整範例:設定 PictureBox 圖片


using namespace System;
using namespace System::Windows::Forms;
using namespace System::Drawing;

ref class ImageHelper {
public:
    static void SetImageSafe(PictureBox^ pPictureBox, Bitmap^ b) {
        if (pPictureBox == nullptr)
            return;

        if (pPictureBox->InvokeRequired) {
            // 使用 MethodInvoker 呼叫同一函式,但於 UI 執行緒執行
            pPictureBox->Invoke(
                gcnew MethodInvoker(gcnew Action(ImageHelper::InvokeCallback), 
                gcnew Tuple(pPictureBox, b))
            );
        } else {
            ApplyImage(pPictureBox, b);
        }
    }

private:
    // 封送的函式代理
    static void InvokeCallback(Object^ state) {
        Tuple^ args = static_cast^>(state);
        ApplyImage(args->Item1, args->Item2);
    }

    // 實際執行設定圖片邏輯
    static void ApplyImage(PictureBox^ pPictureBox, Bitmap^ b) {
        try {
            if (b != nullptr) {
                if (pPictureBox->Image != nullptr)
                    delete pPictureBox->Image;
                pPictureBox->Image = b;
            }
        }
        catch (System::Exception^ ex) {
            Console::WriteLine("設定圖片失敗: " + ex->Message);
        }
    }
};

重點整理



保護 pPictureBox->Image = b 避免程式崩潰

可能發生崩潰的原因

安全設定圖片的建議作法


using namespace System;
using namespace System::Windows::Forms;
using namespace System::Drawing;

void SetImageSafe(PictureBox^ pPictureBox, Bitmap^ b) {
    if (pPictureBox->InvokeRequired) {
        pPictureBox->Invoke(gcnew MethodInvoker(
            gcnew EventHandler(nullptr, &SetImageInvoker)
        ), gcnew array { pPictureBox, b });
    } else {
        SetImageInternal(pPictureBox, b);
    }
}

void SetImageInvoker(Object^ sender, EventArgs^ e) {
    // 不使用此版本,可忽略,保留為完整形式參考
}

void SetImageInternal(PictureBox^ pPictureBox, Bitmap^ b) {
    try {
        if (b != nullptr) {
            if (pPictureBox->Image != nullptr)
                delete pPictureBox->Image;

            pPictureBox->Image = b;
        }
    }
    catch (System::Exception^ ex) {
        Console::WriteLine("設定圖片失敗: " + ex->Message);
    }
}

簡化版本(建議使用匿名委派)

如果你只是要快速保護 `pPictureBox->Image = b;`,以下寫法更直接有效:

using namespace System;
using namespace System::Windows::Forms;
using namespace System::Drawing;

void SafeAssignImage(PictureBox^ pPictureBox, Bitmap^ b) {
    if (pPictureBox->InvokeRequired) {
        pPictureBox->Invoke(gcnew MethodInvoker(gcnew delegate {
            try {
                if (b != nullptr) {
                    if (pPictureBox->Image != nullptr)
                        delete pPictureBox->Image;
                    pPictureBox->Image = b;
                }
            } catch (System::Exception^ ex) {
                Console::WriteLine("設定圖片失敗: " + ex->Message);
            }
        }));
    } else {
        try {
            if (b != nullptr) {
                if (pPictureBox->Image != nullptr)
                    delete pPictureBox->Image;
                pPictureBox->Image = b;
            }
        } catch (System::Exception^ ex) {
            Console::WriteLine("設定圖片失敗: " + ex->Message);
        }
    }
}

補充說明



以 Blazor 建立統一語言的前端開發環境

什麼是 Blazor?

Blazor 是由微軟推出的前端框架,允許開發者使用 C# 和 Razor 語法來建立互動式 Web 應用程式,無需使用 JavaScript,即可在瀏覽器中執行 C# 程式碼。

開發者效益

Blazor 模式

與 .NET 的整合

Blazor 無縫整合 ASP.NET Core,可與現有的 .NET 應用程式結合,並支援依賴注入、路由、元件架構等功能。

部署方式

小結

對於以 .NET 為主要技術的開發者而言,Blazor 提供了與 Node.js 統一 JavaScript 語言相對應的解決方案,使前後端都能使用 C#,建立一致性更高的開發體驗。



使用 .NET MAUI 建立跨平台應用

什麼是 .NET MAUI?

.NET MAUI(Multi-platform App UI)是微軟推出的跨平台應用框架,可使用 C# 和 XAML 撰寫一次程式碼,部署到 Windows、Android、iOS 甚至 macOS。

開發者效益

支援的平台

Blazor Hybrid 模式

可使用 .NET MAUI 的 Blazor Hybrid 模式,在原生應用中嵌入 Web UI,讓開發者用 Razor 組件開發跨平台使用者介面,仍可存取原生 API。

整合與部署

小結

.NET MAUI 是目前最完整的 .NET 跨平台解決方案,可結合 Blazor 達成 Web、桌面與行動平台的統一應用開發,提供給 .NET 開發者一個語言與技術一致的全端體驗。



ASP.NET Core 與 .NET MAUI 的比較

定位

支援平台

開發語言

UI 與互動

適用場景

整合性

.NET MAUI 可透過 API 呼叫與 ASP.NET Core 建立的後端服務整合,形成完整的「前端 App + 後端 API」架構。

總結

ASP.NET Core 解決「後端服務」與「Web 應用」問題,.NET MAUI 則專注在「用戶端跨平台 App」。兩者並不互斥,反而常搭配使用,構成完整解決方案。



簡單的 .NET MAUI 應用範例

建立基本的 .NET MAUI 應用

以下是一個使用 .NET MAUI 建立的跨平台應用程式範例,這個應用在畫面上顯示一個按鈕,點擊後會更新文字計數。

主要檔案:MainPage.xaml


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

    <VerticalStackLayout Spacing="25" Padding="30">
        <Label x:Name="counterLabel"
               Text="你尚未點擊按鈕"
               FontSize="24"
               HorizontalOptions="Center" />

        <Button Text="點我"
                Clicked="OnCounterClicked"
                HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>

後端程式碼:MainPage.xaml.cs


namespace MauiApp;

public partial class MainPage : ContentPage
{
    int count = 0;

    public MainPage()
    {
        InitializeComponent();
    }

    private void OnCounterClicked(object sender, EventArgs e)
    {
        count++;
        counterLabel.Text = $"你已經點擊了 {count} 次";
    }
}

執行方式

小結

這個簡單的範例展示了 .NET MAUI 的跨平台能力,開發者只需撰寫一次 XAML 與 C# 程式碼,即可同時在多個平台運作。



在 Visual Studio 中建立 .NET MAUI 專案

步驟一:安裝必要工具

步驟二:建立新的 MAUI 專案

  1. 開啟 Visual Studio
  2. 點選「建立新專案」
  3. 搜尋並選擇「.NET MAUI App」範本
  4. 按「下一步」,輸入專案名稱與位置
  5. 點選「建立」完成專案初始化

步驟三:了解專案結構

步驟四:執行應用程式

補充說明

小結

使用 Visual Studio 建立 .NET MAUI 專案只需幾個步驟,且能一套程式碼同時部署到多個平台,是現代 C# 全端開發者的理想選擇。



MainPage.xaml 實例與解釋

範例:MainPage.xaml

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

    <VerticalStackLayout Spacing="25" Padding="30"
                         VerticalOptions="Center">

        <Label 
            Text="歡迎使用 .NET MAUI!" 
            SemanticProperties.HeadingLevel="Level1"
            FontSize="32"
            HorizontalOptions="Center" />

        <Button 
            x:Name="counterBtn"
            Text="點我!" 
            Clicked="OnCounterClicked"
            HorizontalOptions="Center" />

    </VerticalStackLayout>

</ContentPage>

對應的 MainPage.xaml.cs

using System;
namespace MyMauiApp;

public partial class MainPage : ContentPage
{
    int count = 0;

    public MainPage()
    {
        InitializeComponent();
    }

    private void OnCounterClicked(object sender, EventArgs e)
    {
        count++;
        counterBtn.Text = $"你已經點了 {count} 次";
    }
}

元件說明

C# 程式碼說明

結果效果

執行後,畫面中央會顯示一個歡迎訊息與一個按鈕。每次點擊按鈕,按鈕上的文字就會更新為「你已經點了 X 次」。



MauiProgram.cs 實例與解釋

範例:MauiProgram.cs

using Microsoft.Extensions.Logging;

namespace MyMauiApp;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        
        builder
            .UseMauiApp() // 指定應用程式的進入點
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });

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

        return builder.Build();
    }
}

功能說明

常見擴充

總結

MauiProgram.cs 就像 ASP.NET Core 的 Startup.csProgram.cs,是應用啟動與服務註冊的主要設定中心。開發大型 MAUI 應用時,擴充此檔案來加入 DI、日誌、組件設定等是非常常見的做法。




email: [email protected]
T:0000
資訊與搜尋 | 回dev首頁
email: Yan Sa [email protected] Line: 阿央
電話: 02-27566655 ,03-5924828
阿央
泱泱科技
捷昱科技泱泱企業