MahApps.Metro WPF UI 指南
用途:為 WPF 應用程式提供 Modern UI(Metro / Fluent 風格)外觀
NuGet:
MahApps.Metro(目前穩定版 2.4+)授權:MIT
支援:.NET Framework 4.6.2+、.NET 5+、.NET 6+、.NET 8+
為什麼選 MahApps.Metro
在工業自動化中,我們的 WPF 設備控制介面需要:
- 清晰的視覺層次(操作員在工廠環境中使用)
- Dark/Light 主題支援(日班/夜班切換)
- 豐富的控件(進度指示、開關切換、飛出面板等)
- 穩定且維護活躍的社群
| 框架 | 優勢 | 劣勢 |
|---|---|---|
| MahApps.Metro | 社群大、控件豐富、穩定 | 風格偏 Metro/Modern |
| HandyControl | 控件數量多、中國社群活躍 | 文件多為中文、風格不統一 |
| MaterialDesignXaml | Material Design 風格精美 | 某些控件與工業場景不搭 |
| WPF UI (Fluent) | Win11 Fluent 風格 | 較新、控件還在成長 |
MahApps.Metro 是公司選擇的標準 UI 框架,提供統一的控件外觀和完整的主題系統。
安裝
dotnet add package MahApps.Metro
dotnet add package MahApps.Metro.IconPacks.Material # 圖示庫(選裝)
基本設定
1. App.xaml — 載入資源字典
<Application x:Class="DeviceControl.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro 主題 -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Dark.Blue.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
2. MainWindow — 使用 MetroWindow
<mah:MetroWindow x:Class="DeviceControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
Title="設備控制台"
Width="1280" Height="800"
WindowStartupLocation="CenterScreen"
GlowBrush="{DynamicResource MahApps.Brushes.Accent}">
<Grid>
<!-- 內容 -->
</Grid>
</mah:MetroWindow>
Code-behind 繼承 MetroWindow:
using MahApps.Metro.Controls;
public partial class MainWindow : MetroWindow
{
public MainWindow()
{
InitializeComponent();
}
}
主題系統
MahApps.Metro 的主題由兩部分組成:Base Theme(Light/Dark)和 Accent Color(強調色)。
主題繼承鏈
主題套用從 App.xaml 的 ResourceDictionary.MergedDictionaries 向下展開,最終覆蓋到每個 MetroWindow 及其子控制項。ControlzEx.Theming.ThemeManager 是執行期切換主題的入口:
要點整理:
Controls.xaml必須最先載入,否則後續 Theme 字典找不到基底樣式會報錯- Theme 字典(
Dark.Blue.xaml等)一次只能存在一個,改主題時由ThemeManager.ChangeTheme負責替換 - 動態切換透過
DynamicResource綁定—控制項自動感知 Theme 字典變動,無需重啟應用程式
內建主題
格式:{BaseTheme}.{AccentColor}
- Base Theme:
Light、Dark - Accent Color:
Red、Green、Blue、Purple、Orange、Lime、Emerald、Teal、Cyan、Cobalt、Indigo、Violet、Pink、Magenta、Crimson、Amber、Yellow、Brown、Olive、Steel、Mauve、Taupe、Sienna
動態切換主題
using ControlzEx.Theming;
// 切換到 Dark + Blue
ThemeManager.Current.ChangeTheme(Application.Current, "Dark.Blue");
// 切換到 Light + Green
ThemeManager.Current.ChangeTheme(Application.Current, "Light.Green");
// 只切換 Base Theme(保留 Accent Color)
var currentTheme = ThemeManager.Current.DetectTheme(Application.Current);
var inverseTheme = ThemeManager.Current.GetInverseTheme(currentTheme);
if (inverseTheme != null)
ThemeManager.Current.ChangeTheme(Application.Current, inverseTheme);
自訂 Accent Color
// 用 RGB 建立自訂強調色
ThemeManager.Current.AddTheme(
RuntimeThemeGenerator.Current.GenerateRuntimeTheme(
"Dark", Color.FromRgb(0x2E, 0x40, 0x57))); // 公司色
ThemeManager.Current.ChangeTheme(Application.Current, "Dark.Runtime");
MVVM 綁定主題切換
// ViewModel
public class SettingsViewModel : ObservableObject
{
private bool _isDarkTheme = true;
public bool IsDarkTheme
{
get => _isDarkTheme;
set
{
if (SetProperty(ref _isDarkTheme, value))
{
var baseTheme = value ? "Dark" : "Light";
ThemeManager.Current.ChangeThemeBaseColor(
Application.Current, baseTheme);
}
}
}
}
<!-- XAML -->
<mah:ToggleSwitch IsOn="{Binding IsDarkTheme}"
OnContent="深色模式"
OffContent="淺色模式" />
MetroWindow 自訂
標題列按鈕
<mah:MetroWindow
ShowMinButton="True"
ShowMaxRestoreButton="True"
ShowCloseButton="True"
ShowIconOnTitleBar="True"
TitleCharacterCasing="Normal">
左側/右側標題命令
<mah:MetroWindow.LeftWindowCommands>
<mah:WindowCommands>
<Button Content="設定" Click="Settings_Click" />
</mah:WindowCommands>
</mah:MetroWindow.LeftWindowCommands>
<mah:MetroWindow.RightWindowCommands>
<mah:WindowCommands>
<Button Content="連線狀態">
<Button.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse Width="8" Height="8"
Fill="{Binding ConnectionColor}" Margin="0,0,5,0"/>
<TextBlock Text="{Binding ConnectionText}" />
</StackPanel>
</DataTemplate>
</Button.ContentTemplate>
</Button>
</mah:WindowCommands>
</mah:MetroWindow.RightWindowCommands>
無框視窗(全螢幕儀表板)
<mah:MetroWindow
ShowTitleBar="False"
WindowStyle="None"
AllowsTransparency="True"
ResizeMode="NoResize"
WindowState="Maximized">
控制項分類
MahApps.Metro 提供的控制項依功能可粗略分為以下四類。實際 API 與範例見常用控件:
選用指引:
- 視窗容器:主應用視窗一律繼承
MetroWindow;獨立內容頁面可用MetroContentControl - 面板 / 導航:
Flyout適合設定面板、詳細資料;HamburgerMenu適合主導航 - 輸入控制項:優先用
ToggleSwitch取代原生CheckBox以維持 Metro 風格;數值輸入用NumericUpDown內建邊界驗證 - 回饋 / 狀態:長時間操作用
ProgressRing;使用者決策用MetroDialog;紅點提示用Badged
本指南結構
| 頁面 | 內容 |
|---|---|
| 概觀與安裝(本頁) | MetroWindow、主題系統、色彩自訂 |
| 常用控件 | Flyout、Dialog、ProgressRing、ToggleSwitch 等 |
| 整合指南 | MVVM、IconPacks、多語系、效能 |