12
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

.NET Core 3.1 GUIテーマ

Last updated at Posted at 2020-09-27

■はじめに

.NET Core 3.1Visual Studioでコントロールの見栄えを変えたり標準以外のコントロールを使ってみます。
000-3.png

キーワード:ライト/ダークテーマ, NumericUpDown, プログレスリング, ウォーターマーク, トグルスイッチ, InputBox

■環境

  • Windows 10
  • Visual Studio 2019 Version 16.7.4
  • .NET Core 3.1
  • MahApps.Metro 2.2.0

■ベース画面作成

こちら を参考に「準備」と「プロジェクトの作成」をしてください。
プロジェクト名はWpfAppThemeSampleにしました。

そして画面を以下のように作成します。

MainWindow.xaml
<Window
    x:Class="WpfAppThemeSample.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:local="clr-namespace:WpfAppThemeSample"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">

    <Window.Resources>
        <!--  タブの既定スタイル  -->
        <Style TargetType="TabItem">
            <Setter Property="Width" Value="120" />
        </Style>
        <!--  ボタンの既定スタイル  -->
        <Style TargetType="Button">
            <Setter Property="Margin" Value="8,8,8,0" />
        </Style>
        <!--  画面下部のボタンスタイル  -->
        <Style x:Key="FooterButton" TargetType="Button">
            <Setter Property="Width" Value="100" />
            <Setter Property="Margin" Value="8,0,0,0" />
        </Style>
        <!--  テキストボックスの既定スタイル  -->
        <Style TargetType="TextBox">
            <Setter Property="Margin" Value="8,8,8,0" />
        </Style>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <!--  テーマ切り替え  -->
        <GroupBox Margin="8" Header="テーマ">
            <StackPanel Orientation="Horizontal">
                <RadioButton
                    Margin="8"
                    Content="ライト"
                    IsChecked="True" />
                <RadioButton Margin="8" Content="ダーク" />
            </StackPanel>
        </GroupBox>

        <TabControl Grid.Row="1" Margin="8">
            <!--#region ■タブ1-->
            <TabItem Header="タブ1" IsSelected="True">
                <ScrollViewer>
                    <StackPanel>
                        <ListBox
                            Width="200"
                            Height="80"
                            Margin="8"
                            HorizontalAlignment="Left"
                            SelectedIndex="2">
                            <ListBoxItem Content="あいうえお" />
                            <ListBoxItem Content="かきくけこ" />
                            <ListBoxItem Content="さしすせそ" />
                            <ListBoxItem Content="たちつてと" />
                            <ListBoxItem Content="なにぬねの" />
                            <ListBoxItem Content="はひふへほ" />
                        </ListBox>
                        <CheckBox
                           Margin="8,8,8,0"
                           Content="チェックボックス"
                           IsChecked="True" />
                        <CheckBox Margin="8,8,8,0" Content="チェックボックス" />
                        <TextBox Text="" />
                        <TextBox Text="" />
                        <Button Content="ボタン" />
                        <Button Content="ボタン" />
                        <Button Content="ボタン" />
                        <Button Content="ボタン" />
                        <Button Content="ボタン" />
                        <Button Content="ボタン" />
                    </StackPanel>

                </ScrollViewer>
            </TabItem>
            <!--#endregion-->

            <!--#region ■タブ2-->
            <TabItem Header="タブ2">
                <StackPanel>
                    <TextBox />
                </StackPanel>
            </TabItem>
            <!--#endregion-->
        </TabControl>

        <StackPanel
            Grid.Row="2"
            Margin="8"
            HorizontalAlignment="Right"
            Orientation="Horizontal">
            <Button Content="InputBox" Style="{StaticResource FooterButton}" />
            <Button Content="ボタン2" Style="{StaticResource FooterButton}" />
            <Button Content="ボタン3" Style="{StaticResource FooterButton}" />
        </StackPanel>
    </Grid>
</Window>

実行してみます。
001.png

■デザインの変更

◇ライブラリのインストール

ソリューションエクスプローラーでプロジェクトを右クリック、メニューからNuGetパッケージの管理を選択します。
002.png

参照タブの検索ボックスにmetroと入力し、MahApps.Metroをインストールします。
003.png

◇App.xamlの修正

ResourceDictionaryを追加します。

App.xaml(修正後)
<Application
    x:Class="WpfAppThemeSample.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfAppThemeSample"
    StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <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/Light.Blue.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

◇MainWindow.xamlの修正

xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"を追加し、
Windowmah:MetroWindowに変更します。

MainWindow.xaml(修正前)
<Window
    x:Class="WpfAppThemeSample.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:local="clr-namespace:WpfAppThemeSample"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d"></Window>
MainWindow.xaml(修正後)
<mah:MetroWindow
    x:Class="WpfAppThemeSample.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:local="clr-namespace:WpfAppThemeSample"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d"></mah:MetroWindow>

スタイル定義にBasedOnを追加します。

MainWindow.xaml(修正後)
        <!--  タブの既定スタイル  -->
        <Style BasedOn="{StaticResource MahApps.Styles.TabItem}" TargetType="TabItem">
            <Setter Property="Width" Value="120" />
        </Style>
        <!--  ボタンの既定スタイル  -->
        <Style BasedOn="{StaticResource MahApps.Styles.Button}" TargetType="Button">
            <Setter Property="Margin" Value="8,8,8,0" />
        </Style>
        <!--  画面下部のボタンスタイル  -->
        <Style
            x:Key="FooterButton"
            BasedOn="{StaticResource MahApps.Styles.Button}"
            TargetType="Button">
            <Setter Property="Width" Value="100" />
            <Setter Property="Margin" Value="8,0,0,0" />
        </Style>
        <!--  テキストボックスの既定スタイル  -->
        <Style BasedOn="{StaticResource MahApps.Styles.TextBox}" TargetType="TextBox">
            <Setter Property="Margin" Value="8,8,8,0" />
        </Style>

◇MainWindow.xaml.csの修正

MainWindow.xaml.csファイルを開き、継承元の記述を消します。
004.png

MainWindow.xaml.cs(修正前)
public partial class MainWindow : Window
MainWindow.xaml.cs(修正後)
public partial class MainWindow

実行してみます。
005.png
デザインが変わりました。

■大文字小文字

タイトルバーのMainWindowと下部ボタンのInputBoxが勝手に大文字に変えられています。
これを無効にして元々設定されたテキストの通りに表示するようにします。

mah:MetroWindowTitleCharacterCasing="Normal"を追加します。
FooterButtonのスタイル定義に<Setter Property="mah:ControlsHelper.ContentCharacterCasing" Value="Normal" />を追加します。

■ウィンドウスタイル設定

◇最大化ボタン、最小化ボタン

ウィンドウのサイズ変更は有効にしたまま、最大化ボタンと最小化ボタンを非表示にします。

mah:MetroWindow
ResizeMode="CanResizeWithGrip"(サイズ変更グリップ表示)、
ShowMaxRestoreButton="False"(最大化ボタン非表示)、
ShowMinButton="False"(最小化ボタン非表示)を追加します。

ここまででXamlは以下のようになっています。

<mah:MetroWindow
    x:Class="WpfAppThemeSample.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:local="clr-namespace:WpfAppThemeSample"
    xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    ResizeMode="CanResizeWithGrip"
    ShowMaxRestoreButton="False"
    ShowMinButton="False"
    TitleCharacterCasing="Normal"
    mc:Ignorable="d">
<!--  画面下部のボタンスタイル  -->
<Style
    x:Key="FooterButton"
    BasedOn="{StaticResource MahApps.Styles.Button}"
    TargetType="Button">
    <Setter Property="Width" Value="100" />
    <Setter Property="Margin" Value="8,0,0,0" />
    <Setter Property="mah:ControlsHelper.ContentCharacterCasing" Value="Normal" />
</Style>

実行してみます。
タイトルバーとボタンの英字がちゃんと指定された通り、大文字小文字が区別されて表示されました。
最小化ボタンと最大化ボタンも消えました。
ウィンドウの右下にサイズ変更がしやすいようにグリップが表示されました。
006.png

◇ウィンドウ縁を光らす

mah:MetroWindowGlowBrush="{DynamicResource MahApps.Brushes.Accent}"を追加します。
ウィンドウの縁がうっすらと光ります。

021.png

拡大
022.png

MainWindow.xaml
<mah:MetroWindow
    x:Class="WpfAppThemeSample.MainWindow"
    
    GlowBrush="{DynamicResource MahApps.Brushes.Accent}"
    
    mc:Ignorable="d">

■ダークテーマ

現在の白基調の配色と、黒基調の配色を切り替えられるようにします。
2つのラジオボタンにCheckedイベントの処理を設定します。

MainWindow.xaml
<!--  テーマ切り替え  -->
<GroupBox Margin="8" Header="テーマ">
    <StackPanel Orientation="Horizontal">
        <RadioButton
            Margin="8"
            Checked="ThemeRadioButton_Checked"
            Content="ライト"
            IsChecked="True" />
        <RadioButton
            Margin="8"
            Checked="ThemeRadioButton_Checked"
            Content="ダーク" />
    </StackPanel>
</GroupBox>
MainWindow.xaml.cs
using ControlzEx.Theming;
using System.Windows;
using System.Windows.Controls;

namespace WpfAppThemeSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void ThemeRadioButton_Checked(object sender, RoutedEventArgs e)
        {
            if (((RadioButton)sender).Content.ToString() == "ライト")
            {
                // ライトテーマを設定
                ThemeManager.Current.ChangeTheme(this, "Light.Blue");
            }
            else
            {
                // ダークテーマを設定
                ThemeManager.Current.ChangeTheme(this, "Dark.Blue");
            }
        }

    }
}

実行してみます。
ダークのラジオボタンを選択すると黒ベースの配色になりました。
007.png

■テキストボックス

タブ2に配置していたテキストボックスを修正します。

◇ウォーターマーク

プレースホルダとも言います。
テキストボックス未入力時に薄く説明文を表示します。
008.png

mah:TextBoxHelper.Watermarkに設定した文字列が、テキストボックス空欄時に薄字で表示されます。

◇テキストクリアボタン

mah:TextBoxHelper.ClearTextButton="True"でテキスト内容をクリアする×ボタンが表示されます。

MainWindow.xaml
<TabItem Header="タブ2">
    <StackPanel>
        <TextBox
            mah:TextBoxHelper.ClearTextButton="True"
            mah:TextBoxHelper.Watermark="何か入力してください。"
            Text="" />
    </StackPanel>
</TabItem>

◇フォーカス時全選択

テキストボックスにフォーカスが来たときに全選択するようにします。
スタイル定義にTextBoxHelper.SelectAllOnFocusを追加します。

MainWindow.xaml(修正後)
<Window.Resources><!--  テキストボックスの既定スタイル  -->
    <Style BasedOn="{StaticResource MahApps.Styles.TextBox}" TargetType="TextBox">
        <Setter Property="Margin" Value="8,8,8,0" />
        <Setter Property="mah:TextBoxHelper.SelectAllOnFocus" Value="True" />
    </Style>
</Window.Resources>

■NumericUpDown

数値入力に適したテキストボックスです。
直接入力することも、+, -ボタンで数値を増減することもできます。
009.png

タブ2の中のStackPanelに以下を追加します。

MainWindow.xaml
<mah:NumericUpDown
    Width="100"
    Margin="8"
    Maximum="999"
    Minimum="1"
    Value="10" />

■トグルスイッチ

On/Offするスイッチです。
(たまに●を一生懸命ドラッグしている人がいますが、クリックで切り替わります)
010.png

タブ2のStackPanelに追加します。

MainWindow.xaml
<mah:ToggleSwitch
    Margin="8"
    Header="何か処理"
    IsOn="False"
    OffContent="停止"
    OnContent="処理中"
    Toggled="ToggleSwitch_Toggled" />
MainWindow.xaml.cs
private void ToggleSwitch_Toggled(object sender, RoutedEventArgs e)
{

}

[参考]ヘッダーもOn/Offのテキスト切り替えも不要な場合はContentにテキストを設定します。
023.png

<mah:ToggleSwitch Content="電源" IsOn="True"/>

■プログレスリング

処理中表示に使う、●がぐるぐる回るやつです。
011.png

タブ2のStackPanelに追加します。

MainWindow.xaml
<mah:ProgressRing x:Name="ProgressR" IsActive="False" />

トグルスイッチ切り替え時の処理を記述します。
トグルスイッチがOnになったら処理中表示にするようにします。

MainWindow.xaml.cs
private void ToggleSwitch_Toggled(object sender, RoutedEventArgs e)
{
    ProgressR.IsActive = ((MahApps.Metro.Controls.ToggleSwitch)sender).IsOn;
}

012.png

■InputBox

文字入力するためのポップアップ画面です。
013.png

InputBoxボタンにClickイベントの処理を追加します。

MainWindow.xaml
<Button
    Click="InputBoxButton_Click"
    Content="InputBox"
    Style="{StaticResource FooterButton}" />
<Button Content="ボタン2" Style="{StaticResource FooterButton}" />
<Button Content="ボタン3" Style="{StaticResource FooterButton}" />

MahApps.Metro.Controls.Dialogsをusingしておきます。
InputBoxButton_Click定義にasyncを付け足してください。
ShowInputAsyncでInputBoxを表示します。

MainWindow.xaml.cs
using MahApps.Metro.Controls.Dialogs;


private async void InputBoxButton_Click(object sender, RoutedEventArgs e)
{
    var settings = new MetroDialogSettings() { DefaultText = "最初に表示しておく文字列" };
    string result = await this.ShowInputAsync(
        "タイトル", "何か入力してください。", settings);
    if (result == null)
    {
        // キャンセル
        return;
    }
    else
    {
        await this.ShowMessageAsync("タイトル", $"「{result}」が入力されました。");
    }
}

■タブ

◇タブ切り替え時にアニメーション

TabControlmah:MetroAnimatedTabControlに変更するとタブ切り替え時に中身が少しスライドして表示されるようになります。

MainWindow.xaml(修正前)
<TabControl Grid.Row="1" Margin="8">
MainWindow.xaml(修正後)
<mah:MetroAnimatedTabControl Grid.Row="1" Margin="8">

◇アクティブタブに下線

アクティブなタブに下線を表示します。

015.png

タブコントロールにTabControlHelper.Underlineを設定します。

MainWindow.xaml(修正後)
<mah:MetroAnimatedTabControl
    Grid.Row="1"
    Margin="8"
    mah:TabControlHelper.Underlined="SelectedTabItem">
12
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?