WPFでモダンなユーザーインターフェースを構築する方法として、MaterialDesign、MahApps、Dragablzのライブラリが有名です。これらのライブラリを使えば、視覚的に美しいデザインと実用的な機能性を簡単に実現できます。
この記事では、これら3つのライブラリを使って、シンプルかつ効率的なWPFモダンUIの作り方をステップバイステップで紹介します。WPFでの開発にモダンな要素を取り入れたい方や、より使いやすいUIを構築したい方に最適です。
はじめに
MaterialDesignの公式サイトにおいて、MahAppsとDragablz を同時に使えることが記載されていたので、上記のサンプルプログラムを作ってみました。
Dragablz の公式サイトで紹介している方法(App.xamlの修正)をそのまま適用すると、2か所で参照先が存在しないというエラーが発生したため、存在する参照先に変更しています。
また、ライブラリ3つを同時に利用する場合、App.xamlとMainWindow.xaml にそれなりの手を加える必要があります。修正量が多いため難しく感じるかもしれませんが、本記事では図を使って具体的な変更箇所を明確にしていますので、手順通りに修正していけば問題なくできると思います。
記事の後半には、App.xaml、MainWindow.xaml、MainWindow.csの修正済みソースコードを掲載していますので、ゼロからプログラムを作る方は、そのままコピペして(プログラム名はご自身のものに修正が必要)お使い下さい。
インストール方法
Nugetから次のライブラリを検索し、インストールします。
MaterialDesignThemes
ShowMeTheXAML.MSBuild
MaterialDesignColors
MahApps.Metro
Dragablz
それぞれの詳しいインストール方法、組み込み方を知りたい方は、次の記事をご一読ください。
プロジェクトへの組み込み方法
App.xamlと MaiNWindow.xaml の2か所を修正する必要があります。
App.xamlの修正
上記①の位置に、次のソースコードを挿入します。
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
上記②の位置に、次のソースコードを挿入します。
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- メインのカラー -->
<ResourceDictionary>
<!-- テーマと色の設定 -->
<ResourceDictionary.MergedDictionaries>
<!-- Material Desing のテーマ設定 -->
<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign2.Defaults.xaml" />
<!-- Dragablz のテーマ設定 -->
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/MaterialDesignColor.Indigo.xaml" />
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<!-- Theme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
</ResourceDictionary.MergedDictionaries>
<!--
メインパレットから3つの色調と関連する前景色を含める。
名前を変更せず、薄い色から濃い色まで順序を保つ。
-->
<SolidColorBrush x:Key="PrimaryHueLightBrush" Color="{StaticResource Primary100}"/>
<SolidColorBrush x:Key="PrimaryHueLightForegroundBrush" Color="{StaticResource Primary100Foreground}"/>
<SolidColorBrush x:Key="PrimaryHueMidBrush" Color="{StaticResource Primary500}"/>
<SolidColorBrush x:Key="PrimaryHueMidForegroundBrush" Color="{StaticResource Primary500Foreground}"/>
<SolidColorBrush x:Key="PrimaryHueDarkBrush" Color="{StaticResource Primary700}"/>
<SolidColorBrush x:Key="PrimaryHueDarkForegroundBrush" Color="{StaticResource Primary700Foreground}"/>
</ResourceDictionary>
<!-- サブカラー -->
<ResourceDictionary>
<!-- サブパレットを含める -->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/MaterialDesignColor.Yellow.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- 単一のサブアクセントカラーと関連する前景色を含める -->
<SolidColorBrush x:Key="SecondaryAccentBrush" Color="{StaticResource Secondary200}"/>
<SolidColorBrush x:Key="SecondaryAccentForegroundBrush" Color="{StaticResource Secondary200Foreground}"/>
</ResourceDictionary>
<!-- DragablzのMaterial Designスタイルを含める -->
<ResourceDictionary Source="pack://application:,,,/Dragablz;component/Themes/materialdesign.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- DragablzタブコントロールにMaterial Designテーマを使用するように設定 -->
<Style TargetType="{x:Type dragablz:TabablzControl}" BasedOn="{StaticResource MaterialDesignTabablzControlStyle}" />
</ResourceDictionary>
MainWindow.xamlの修正
①の箇所に次の5行を挿入します。
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
xmlns:dockablz="clr-namespace:Dragablz.Dockablz;assembly=Dragablz"
xmlns:system="clr-namespace:System;assembly=mscorlib"
②の箇所に次の3行を挿入します。
<Window.Resources>
<system:String x:Key="Partition">Beginning</system:String>
</Window.Resources>
③の位置に次の11行を挿入します。
<dockablz:Layout Partition="{StaticResource Partition}" Grid.ColumnSpan="3">
<dragablz:TabablzControl>
<dragablz:TabablzControl.InterTabController>
<dragablz:InterTabController Partition="{StaticResource Partition}"/>
</dragablz:TabablzControl.InterTabController>
<TabItem Header="Tab1" />
<TabItem Header="Tab2" />
<TabItem Header="Tab3" />
</dragablz:TabablzControl>
</dockablz:Layout>
④の箇所(上下2か所)の Windowタグを mah:MetroWindow に書き換えます。。
mah:MetroWindow>
MainWindow.csの修正
MainWindowクラスの継承元を Window から MetroWindow に変更します。
MetroWindow
サンプルプログラム
MaterialDesign、MahApps、Dragablz の3つを融合させたUIのサンプルです。ModernUISample という名前でプロジェクトを作成し、ソースコードをそのままコピペして張り付けると動作します。
注意点としては、それぞれのテーマが影響しているため、微調整が難しいことでしょう。
例えば、Dragablz のタブを選んだ際、アクティブなタブに黄色のアンダーラインが表示されるべきですが、表示されません。また、TabPage内に存在するTabControlの文字色が薄いグレーになっていますが、これらは3つのテーマが競合しているためだと思われます。
とはいうものの、いくつかの点を妥協すればモダンなデザインが簡単に実現できます。
App.xaml
<Application x:Class="ModernUISample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
xmlns:local="clr-namespace:ModernUISample"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- メインのカラー -->
<ResourceDictionary>
<!-- テーマと色の設定 -->
<ResourceDictionary.MergedDictionaries>
<!-- Material Desing のテーマ設定 -->
<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign2.Defaults.xaml" />
<!-- Dragablz のテーマ設定 -->
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/MaterialDesignColor.Indigo.xaml" />
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<!-- Theme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
</ResourceDictionary.MergedDictionaries>
<!--
メインパレットから3つの色調と関連する前景色を含める。
名前を変更せず、薄い色から濃い色まで順序を保つ。
-->
<SolidColorBrush x:Key="PrimaryHueLightBrush" Color="{StaticResource Primary100}"/>
<SolidColorBrush x:Key="PrimaryHueLightForegroundBrush" Color="{StaticResource Primary100Foreground}"/>
<SolidColorBrush x:Key="PrimaryHueMidBrush" Color="{StaticResource Primary500}"/>
<SolidColorBrush x:Key="PrimaryHueMidForegroundBrush" Color="{StaticResource Primary500Foreground}"/>
<SolidColorBrush x:Key="PrimaryHueDarkBrush" Color="{StaticResource Primary700}"/>
<SolidColorBrush x:Key="PrimaryHueDarkForegroundBrush" Color="{StaticResource Primary700Foreground}"/>
</ResourceDictionary>
<!-- サブカラー -->
<ResourceDictionary>
<!-- サブパレットを含める -->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/MaterialDesignColor.Yellow.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- 単一のサブアクセントカラーと関連する前景色を含める -->
<SolidColorBrush x:Key="SecondaryAccentBrush" Color="{StaticResource Secondary200}"/>
<SolidColorBrush x:Key="SecondaryAccentForegroundBrush" Color="{StaticResource Secondary200Foreground}"/>
</ResourceDictionary>
<!-- DragablzのMaterial Designスタイルを含める -->
<ResourceDictionary Source="pack://application:,,,/Dragablz;component/Themes/materialdesign.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- DragablzタブコントロールにMaterial Designテーマを使用するように設定 -->
<Style TargetType="{x:Type dragablz:TabablzControl}" BasedOn="{StaticResource MaterialDesignTabablzControlStyle}" />
</ResourceDictionary>
</Application.Resources>
</Application>
MainWindow.xaml
<mah:MetroWindow x:Class="ModernUISample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
xmlns:dockablz="clr-namespace:Dragablz.Dockablz;assembly=Dragablz"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:ModernUISample"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<!--マウスによるレイアウト変更を実現するための定義 -->
<system:String x:Key="Partition">Beginning</system:String>
</Window.Resources>
<Grid>
<!-- マウスによるレイアウト変更を実現するためのコンテナ -->
<dockablz:Layout Partition="{StaticResource Partition}">
<!--マウスによるタブの並べ替えが可能な dragablzのTabControl -->
<dragablz:TabablzControl Margin="0,59,0,0">
<!-- タブの分離とドッキングを実現するための定義 -->
<dragablz:TabablzControl.InterTabController>
<dragablz:InterTabController Partition="{StaticResource Partition}"/>
</dragablz:TabablzControl.InterTabController>
<!--Dragablzの管理下にあるタブページ -->
<TabItem Header="HELLO">
<!--タブページ内に定義したタブ(Dragablzの管理外となる)にMaterialDesign のスタイルを使用 -->
<TabControl materialDesign:ColorZoneAssist.Mode="SecondaryLight"
Style="{StaticResource MaterialDesignFilledTabControl}" Margin="10">
<TabItem Header="標準Tab1">
<StackPanel>
<TextBlock HorizontalAlignment="Center" Margin="10">Hello World</TextBlock>
<ToggleButton IsChecked="True" Style="{StaticResource MaterialDesignSwitchDarkToggleButton}" Margin="10"/>
<ComboBox Width="200" Style="{StaticResource MaterialDesignFilledComboBox}" Margin="10"></ComboBox>
<Slider Width="200" Style="{StaticResource MaterialDesignDiscreteSlider}" Margin="10"></Slider>
<Button Content="Button" Style="{StaticResource MaterialDesignRaisedDarkButton}" Width="200"></Button>
</StackPanel>
</TabItem>
<TabItem Header="標準Tab2">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">Hello World</TextBlock>
</TabItem>
</TabControl>
</TabItem>
<!--Dragablzの管理下にあるタブページ -->
<TabItem Header="MATERIAL">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">Material Design</TextBlock>
</TabItem>
<!--Dragablzの管理下にあるタブページ -->
<TabItem Header="DESIGN">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">Looks Quite Nice</TextBlock>
</TabItem>
</dragablz:TabablzControl>
</dockablz:Layout>
</Grid>
</mah:MetroWindow>
MainWindow.cs
using MahApps.Metro.Controls;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ModernUISample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : MetroWindow
{
public MainWindow()
{
InitializeComponent();
}
}
}
まとめ
今回の記事では、MaterialDesign、MahApps、Dragablzの3つのライブラリを組み合わせて、WPFアプリケーションでドッキング可能なモダンUIを実現する方法を紹介しました。
これらのライブラリを使用することで、見た目だけでなく、操作性や柔軟性に優れたUIを簡単に構築することが可能です。
MaterialDesignでスタイリッシュなフラットデザインを適用し、MahAppsで使い勝手の良いカスタムウィンドウを提供し、Dragablzによってドッキングやタブの管理を実装しました。これにより、モダンでインタラクティブなUIを実現し、ユーザー体験を向上させることができるでしょう。
ぜひ、今回紹介した手法を活用して、あなたのアプリケーションにモダンな要素を取り入れてみてください。UIが進化することで、アプリ全体の価値も一段と高まります。
コメント