常用控件
本頁列出公司專案中最常用的 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、多語系整合