Skip to main content

常用控件

本頁列出公司專案中最常用的 MahApps.Metro 控件,每個附上 XAML 範例和工業場景用法。

XAML namespace:xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"


Flyout — 側邊飛出面板

從視窗邊緣滑出的面板,適合設備設定、詳細資訊等非主要畫面。

<!-- 在 MetroWindow 中定義 Flyout -->
<mah:MetroWindow.Flyouts>
<mah:FlyoutsControl>
<mah:Flyout x:Name="DeviceSettingsFlyout"
Header="設備設定"
Position="Right"
Width="400"
Theme="Adapt">
<StackPanel Margin="16">
<TextBlock Text="通訊設定" Style="{StaticResource MahApps.Styles.TextBlock.Header}" />
<mah:NumericUpDown Minimum="1" Maximum="65535"
Value="{Binding Port}"
mah:TextBoxHelper.Watermark="Port" />
<mah:ToggleSwitch IsOn="{Binding AutoReconnect}"
OnContent="自動重連:開"
OffContent="自動重連:關" Margin="0,8,0,0" />
<Button Content="儲存" Command="{Binding SaveCommand}"
Style="{StaticResource MahApps.Styles.Button.Dialogs.Accent}"
Margin="0,16,0,0" />
</StackPanel>
</mah:Flyout>
</mah:FlyoutsControl>
</mah:MetroWindow.Flyouts>

開關 Flyout:

DeviceSettingsFlyout.IsOpen = !DeviceSettingsFlyout.IsOpen;

MVVM 綁定:

<mah:Flyout IsOpen="{Binding IsSettingsOpen}" ... />

Dialog — 非同步對話框

MahApps 的 Dialog 是 async/await 友好的,不會阻塞 UI 線程。

MessageDialog

using MahApps.Metro.Controls.Dialogs;

// 在 MetroWindow 或 ViewModel 中使用
var result = await this.ShowMessageAsync(
"確認操作",
"確定要停止設備運轉?此操作不可復原。",
MessageDialogStyle.AffirmativeAndNegative,
new MetroDialogSettings
{
AffirmativeButtonText = "確定停止",
NegativeButtonText = "取消",
DefaultButtonFocus = MessageDialogResult.Negative
});

if (result == MessageDialogResult.Affirmative)
{
await StopDeviceAsync();
}

InputDialog

var input = await this.ShowInputAsync(
"設定參數",
"請輸入新的溫度上限值 (°C):");

if (double.TryParse(input, out var maxTemp))
{
await SetTemperatureLimitAsync(maxTemp);
}

ProgressDialog

var controller = await this.ShowProgressAsync(
"設備初始化",
"正在連線到 PLC...",
isCancelable: true);

controller.SetIndeterminate(); // 不確定進度

try
{
await ConnectToPlcAsync();
controller.SetMessage("正在校準感測器...");
controller.SetProgress(0.5);
await CalibrateSensorsAsync();
controller.SetProgress(1.0);
}
finally
{
await controller.CloseAsync();
}

MVVM 中使用 Dialog

透過 IDialogCoordinator 注入:

// 註冊
services.AddSingleton<IDialogCoordinator>(DialogCoordinator.Instance);

// ViewModel
public class DeviceViewModel
{
private readonly IDialogCoordinator _dialogCoordinator;

public DeviceViewModel(IDialogCoordinator dialogCoordinator)
{
_dialogCoordinator = dialogCoordinator;
}

public async Task StopDevice()
{
var result = await _dialogCoordinator.ShowMessageAsync(
this, // context 必須是 ViewModel 本身
"確認", "確定要停止?",
MessageDialogStyle.AffirmativeAndNegative);
}
}

XAML 設定 context:

<mah:MetroWindow
xmlns:dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
dialog:DialogParticipation.Register="{Binding}">

ProgressRing / ProgressBar

ProgressRing — 載入指示

<!-- 不確定進度(轉圈圈) -->
<mah:ProgressRing IsActive="{Binding IsLoading}" Width="60" Height="60" />

<!-- 搭配 Visibility -->
<mah:ProgressRing IsActive="{Binding IsConnecting}"
Visibility="{Binding IsConnecting, Converter={StaticResource BoolToVis}}" />

MetroProgressBar — 進度條

<!-- 不確定進度 -->
<mah:MetroProgressBar IsIndeterminate="True"
Visibility="{Binding IsBusy, Converter={StaticResource BoolToVis}}" />

<!-- 確定進度 -->
<mah:MetroProgressBar Value="{Binding Progress}"
Maximum="100"
Foreground="{DynamicResource MahApps.Brushes.Accent}" />

ToggleSwitch — 開關切換

適合設備啟停控制、功能開關。

<mah:ToggleSwitch IsOn="{Binding IsDeviceRunning}"
OnContent="運轉中"
OffContent="已停止"
Toggled="DeviceToggle_Toggled" />

<!-- 唯讀狀態顯示 -->
<mah:ToggleSwitch IsOn="{Binding IsConnected, Mode=OneWay}"
OnContent="已連線"
OffContent="已斷線"
IsEnabled="False" />

NumericUpDown — 數值輸入

適合設備參數設定(溫度、壓力、速度)。

<mah:NumericUpDown Value="{Binding Temperature}"
Minimum="0"
Maximum="200"
Interval="0.5"
StringFormat="F1"
NumericInputMode="Decimal"
mah:TextBoxHelper.Watermark="溫度設定 (°C)" />

<!-- 整數模式 -->
<mah:NumericUpDown Value="{Binding SpindleSpeed}"
Minimum="0"
Maximum="10000"
Interval="100"
NumericInputMode="Numbers"
mah:TextBoxHelper.Watermark="轉速 (RPM)" />

Tile — Dashboard 磚塊

適合儀表板主畫面的大按鈕/資訊磚塊。

<WrapPanel>
<mah:Tile Title="溫度" Width="180" Height="180"
Count="{Binding Temperature, StringFormat={}{0:F1}°C}"
Background="{DynamicResource MahApps.Brushes.Accent}"
Click="TempTile_Click" />

<mah:Tile Title="壓力" Width="180" Height="180"
Count="{Binding Pressure, StringFormat={}{0:F2} MPa}"
Background="#FF2D7D9A" />

<mah:Tile Title="警報" Width="180" Height="180"
Count="{Binding AlarmCount}"
Background="{Binding HasAlarm, Converter={StaticResource AlarmColorConverter}}" />
</WrapPanel>

DataGrid 樣式

MahApps 自動套用 Metro 風格到標準 DataGrid。

<DataGrid ItemsSource="{Binding DeviceRecords}"
AutoGenerateColumns="False"
IsReadOnly="True"
SelectionMode="Single"
mah:DataGridHelper.EnableCellEditAssist="True">
<DataGrid.Columns>
<DataGridTextColumn Header="時間" Binding="{Binding Timestamp, StringFormat=HH:mm:ss}" />
<DataGridTextColumn Header="參數" Binding="{Binding ParameterName}" />
<DataGridTextColumn Header="數值" Binding="{Binding Value, StringFormat=F2}" />
<DataGridTextColumn Header="狀態" Binding="{Binding Status}" />
</DataGrid.Columns>
</DataGrid>

HamburgerMenu — 導航選單

適合多功能的設備監控介面。

<mah:HamburgerMenu x:Name="HamburgerMenuControl"
DisplayMode="CompactInline"
IsPaneOpen="{Binding IsMenuOpen}"
ItemInvoked="HamburgerMenu_ItemInvoked">

<mah:HamburgerMenu.ItemsSource>
<mah:HamburgerMenuItemCollection>
<mah:HamburgerMenuIconItem Label="儀表板" Tag="Dashboard">
<mah:HamburgerMenuIconItem.Icon>
<iconPacks:PackIconMaterial Kind="ViewDashboard" Width="24" Height="24" />
</mah:HamburgerMenuIconItem.Icon>
</mah:HamburgerMenuIconItem>
<mah:HamburgerMenuIconItem Label="設備監控" Tag="Monitor">
<mah:HamburgerMenuIconItem.Icon>
<iconPacks:PackIconMaterial Kind="Monitor" Width="24" Height="24" />
</mah:HamburgerMenuIconItem.Icon>
</mah:HamburgerMenuIconItem>
<mah:HamburgerMenuIconItem Label="參數設定" Tag="Settings">
<mah:HamburgerMenuIconItem.Icon>
<iconPacks:PackIconMaterial Kind="Cog" Width="24" Height="24" />
</mah:HamburgerMenuIconItem.Icon>
</mah:HamburgerMenuIconItem>
</mah:HamburgerMenuItemCollection>
</mah:HamburgerMenu.ItemsSource>

<!-- 內容區域 -->
<mah:HamburgerMenu.ContentTemplate>
<DataTemplate>
<ContentControl Content="{Binding Tag}" />
</DataTemplate>
</mah:HamburgerMenu.ContentTemplate>
</mah:HamburgerMenu>

BadgedControl — 通知徽章

<!-- 警報數量徽章 -->
<mah:Badged Badge="{Binding AlarmCount}"
BadgePlacementMode="TopRight">
<Button Content="警報"
Style="{StaticResource MahApps.Styles.Button.Square.Accent}" />
</mah:Badged>

<!-- 連線狀態點 -->
<mah:Badged Badge=""
BadgeBackground="{Binding IsConnected,
Converter={StaticResource BoolToBrushConverter}}"
BadgePlacementMode="BottomRight">
<TextBlock Text="PLC-1" />
</mah:Badged>

TextBoxHelper — 浮水印與清除按鈕

MahApps 為標準 TextBox 提供附加屬性:

<TextBox mah:TextBoxHelper.Watermark="搜尋設備..."
mah:TextBoxHelper.ClearTextButton="True"
mah:TextBoxHelper.UseFloatingWatermark="True" />

自訂控件樣式

Override 全局樣式

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps 資源(先載入) -->
<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>

<!-- 自訂覆寫(放在 MergedDictionaries 後面) -->
<Style TargetType="Button" BasedOn="{StaticResource MahApps.Styles.Button}">
<Setter Property="MinHeight" Value="36" />
<Setter Property="Padding" Value="16,8" />
</Style>
</ResourceDictionary>
</Application.Resources>

針對單一控件 Override

<Button Content="緊急停機"
Style="{StaticResource MahApps.Styles.Button.Square}">
<Button.Resources>
<SolidColorBrush x:Key="MahApps.Brushes.Button.Square.Background.MouseOver"
Color="#FFCC0000" />
</Button.Resources>
</Button>

下一步整合指南 — MVVM 框架、IconPacks、多語系整合