WPFの機能であるスタイル、テンプレートを使用してボタンとプログレスバーのUIをカスタマイズしてみました。メモとして記載を行います。

動作確認環境

  • 動作環境:Windows Server 2003
  • 開発環境:Visual Studio 2008 Professional
  • .NET 3.5

1. 今回作成するボタンとプログレスバー

今回StyleとTemplateを使用して作成するプログラムの完成結果の画面イメージを掲載します。一番上がマウスがオーバーしたときのボタンで、真ん中が通常時のボタン。3番目がプログレスバーです。

 

 

今回は図のように赤い光沢のあるButtonとProgressbarを作成してみます。

2. カスタマイズボタンを作成する

Visual Studio を起動してソリューションを新規作成します。ソリューション名はWPFTemplateLibraryという名前で作成しました。

2.1 WPF クラスライブラリの作成

ソリューションエクスプローラを右クリックし、WPFGlassというWPFクラスライブラリを作成します。

作成後、プロジェクトを右クリックし、追加→リソースディディクショナリを選択し、CommonResource.xamlという名前でファイル名で作成します。

リソースファイルはボタンやプログレスバーの共通リソースを定義したものです。次のように編集します。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <!-- テキスト -->
    <SolidColorBrush x:Key="TextBrush" Color="White" />
    
    <!-- バックグラウンドの定義 -->
    <!-- 通常のバックグラウンド -->
    <LinearGradientBrush x:Key="ControlBackground" StartPoint="0,0" EndPoint="0,1">
        <GradientStop Offset="0" Color="#FFFF0000" />
        <GradientStop Offset="0.5" Color="#FFFF0000" />
        <GradientStop Offset="1" Color="#AADD4433" />
    </LinearGradientBrush>
    <!-- ボーダーカラー -->
    <LinearGradientBrush x:Key="ControlBorder" StartPoint="0,0" EndPoint="0,1">
        <GradientStop Offset="0" Color="#AAFF0000" />
        <GradientStop Offset="0.8" Color="#AAFF0000" />
    </LinearGradientBrush>
    <!-- マウスオーバー時のバックグラウンド -->
    <LinearGradientBrush x:Key="ControlBackgroundMouserOver" StartPoint="0,0" EndPoint="0,1">
        <GradientStop Offset="0" Color="#FFFF0000" />
        <GradientStop Offset="1" Color="#DDFF44FF" />
    </LinearGradientBrush>
    <LinearGradientBrush x:Key="ControlBackgroundMousePressed" StartPoint="0,0" EndPoint="0,1">
        <GradientStop Offset="0" Color="#CCFFFFFF" />
        <GradientStop Offset="0.1" Color="#CCFFFFFF" />
        <GradientStop Offset="0.4" Color="#88FFFFFF" />
        <GradientStop Offset="0.4" Color="#00FFFFFF" />
    </LinearGradientBrush>
    <!-- 光沢 -->
    <LinearGradientBrush x:Key="ControlWhiteTop" StartPoint="0,0" EndPoint="0,1">
        <GradientStop Offset="0" Color="#CCFFFFFF" />
        <GradientStop Offset="0.1" Color="#CCFFFFFF" />
        <GradientStop Offset="0.4" Color="#88FFFFFF" />
        <GradientStop Offset="0.4" Color="#00FFFFFF" />
    </LinearGradientBrush>
    <RadialGradientBrush x:Key="ControlWhiteBottom"
          GradientOrigin="0.5,1.0"
          Center="0.5,1.0" RadiusX="0.7" RadiusY="0.1">
        <RadialGradientBrush.GradientStops>
            <GradientStop Color="#AAFFFFFF" Offset="0" />
            <GradientStop Color="#00FFFFFF" Offset="1" />
        </RadialGradientBrush.GradientStops>
    </RadialGradientBrush>
</ResourceDictionary>

次に、赤いボタン用のリソースディクショナリを作成します。プロジェクトを右クリックし、追加→リソースディクショナリを選択肢、RedButton.xamlを作成します。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="CommonResource.xaml" />
        <ResourceDictionary Source="RedProgressBar.xaml" />
    </ResourceDictionary.MergedDictionaries>
    
    <Style x:Key="ForcusDefaultStyle" TargetType="{x:Type Control}" >
        
    </Style>
    <Style x:Key="RedButton" TargetType="{x:Type Button}">
        <Setter Property="Margin" Value="1"></Setter>
        <Setter Property="Padding" Value="14" />
        <Setter Property="SnapsToDevicePixels" Value="false"></Setter>
        <Setter Property="OverridesDefaultStyle" Value="true"></Setter>
        <Setter Property="MinHeight" Value="20"></Setter>
        <Setter Property="MinWidth" Value="16"></Setter>
        <Setter Property="FontFamily" Value="Verdana"></Setter>
        <Setter Property="FontSize" Value="11px"></Setter>
        <Setter Property="Foreground" Value="{StaticResource TextBrush}"></Setter>
        <Setter Property="FocusVisualStyle" Value="{StaticResource ForcusDefaultStyle}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid x:Name="Content" RenderTransformOrigin="0.5,0.5">
                        <!-- ボーダー描画 -->
                        <Border Name="border" CornerRadius="9" Background="{StaticResource ControlBackground}"
                                BorderBrush="{StaticResource ControlBorder}" BorderThickness="1">
                        </Border>
                        <!-- background -->
                        <Rectangle x:Name="top" Margin="1,1,1,1" RadiusX="9" RadiusY="9" Fill="{StaticResource ControlWhiteTop}" >
                        </Rectangle>
                        <Rectangle x:Name="bottom" Margin="1,1,1,1" RadiusX="9" RadiusY="9" Fill="{StaticResource ControlWhiteBottom}" >
                        </Rectangle>
                        <ContentPresenter Margin="4" x:Name="innerContent" VerticalAlignment="Center" HorizontalAlignment="Center" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter TargetName="border" Property="Background" Value="{StaticResource ControlBackgroundMouserOver}" />
                        </Trigger>
                        <Trigger Property="IsPressed" Value="true">
                            <Setter TargetName="top" Property="Fill" Value="{StaticResource ControlBackgroundMousePressed}" />
                            <Setter TargetName="innerContent" Property="RenderTransform">
                                <Setter.Value>
                                    <TranslateTransform X="0" Y="1" />
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

次に、赤いプログレスバー用のリソースディクショナリを作成します。プロジェクトを右クリックし、追加→リソースディクショナリを選択、RedProgressBar.xamlというファイル名で作成し次のように編集します。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="CommonResource.xaml" />
    </ResourceDictionary.MergedDictionaries>
    <LinearGradientBrush x:Key="ProgressBackground" StartPoint="0,0" EndPoint="0,1">
        <GradientStop Offset="0" Color="#888888" />
        <GradientStop Offset="1" Color="#AAAAAA" />
    </LinearGradientBrush>
    <Style TargetType="{x:Type ProgressBar}">
        <Setter Property="MinHeight" Value="15" />
        <Setter Property="MinWidth" Value="100" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ProgressBar}">
                    <Grid>
                        <Border Name="PART_Track" CornerRadius="1" Background="{StaticResource ProgressBackground}" BorderThickness="1" BorderBrush="{StaticResource ControlBorder}"></Border>
                        <Grid Name="PART_Indicator" HorizontalAlignment="Left" >
                            <Rectangle x:Name="prgBackground" Margin="0" RadiusX="1" RadiusY="1" Fill="{StaticResource ControlBackground}" >
                            </Rectangle>
                            <Rectangle x:Name="Highlight1" Margin="1" RadiusX="1" RadiusY="1" Opacity="1" Fill="{StaticResource ControlWhiteTop}">
                            </Rectangle>
                            <Rectangle x:Name="Highlight2" Margin="0" RadiusX="1" RadiusY="1" Opacity="1" Fill="{StaticResource ControlWhiteBottom}">
                            </Rectangle>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

最後に、ユーザコントロール用のxamlを作成します。プロジェクトを右クリックし、追加ダイアログで、テンプレートにユーザコントロール(WPF)を選択し、UserControl1という名前で作成します。これでボタンと、プログレスバーに作成したスタイルが適用されるようになります。

<UserControl x:Class="WPFGlass.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    >
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="RedButton.xaml" />
                <ResourceDictionary Source="RedProgressBar.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <StackPanel>
        <Button Style="{StaticResource RedButton}" x:Name="btnSample1" Content="ClickMe!!"/>
        <Button Style="{StaticResource RedButton}" x:Name="btnSample2" Content="MouseOver"/>
        <ProgressBar x:Name="prgBar" Value="40" />
    </StackPanel>
</UserControl>

2.2 WPFアプリケーションを作成

2.1で作成したユーザコントロールを表示するプログラムを作成します。ソリューションを右クリックし、WPFアプリケーションプロジェクトを新規作成します。プロジェクト名は WpfApplication1 としました。

プロジェクト作成後、2.1のWPFクラスライブラリを参照に加えて、既定で作成されるWindows1.xamlを次のように編集して、完了です。

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:WPFGlass;assembly=WPFGlass"
    Title="Window1" >
    <Grid>
        <custom:UserControl1 x:Name="userControl" />
    </Grid>
</Window>

3. まとめ

WPFは今までのものと比べれば簡単にカスタマイズされたUIを簡単に作成できます。ただ、懲りすぎないように注意したほうがよさそうです。