LoginSignup
0
2

More than 3 years have passed since last update.

DictionaryでCustom Buttonを作り、MainWindowで使用する方法

Posted at

やりたい事

1. 自分でボタンをデザインしたい。
2. 詳細デザインをDictionary.xamlに記述し、"CustomButton"をMainWindow.xamlで使用する。MainWindow.xaml内部をすっきりさせたい。

結果

下の画像が結果である。
一番上(Button1)は、Windowsのチュートリアル[1]に記述されていたもの。二番目(Button2)は、参考文献[2]に記述されていたもの。三番目(Button3)は、デフォルトを表わす。
image.png

参考文献

[1] Microsoftのチュートリアル
自分の知識レベルが低いのか? Microsoftのreferenceは分かりにくい。でもこのチュートリアルは分かりやすいです。
[2] XAML UNLEASHED
xamlは、記述方法の慣れが必要で、参考資料が少ないですが、この書籍は分かりやすいと思います。初心者には、こちらを勧めます。しかも、中古本が安い。

詳細

自分でデザインしたボタンをDictionary.xamlに記述します。
ここで、デザインといっても、pngやjpgなどで作った画像データを埋め込むという意味ではありません。

Dictionary1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApp5">
    <GradientStopCollection x:Key="MyGlassGradientStopsResource">
        <GradientStop Color="WhiteSmoke" Offset="0.2" />
        <GradientStop Color="Transparent" Offset="0.4" />
        <GradientStop Color="WhiteSmoke" Offset="0.5" />
        <GradientStop Color="Transparent" Offset="0.75" />
        <GradientStop Color="WhiteSmoke" Offset="0.9" />
        <GradientStop Color="Transparent" Offset="1" />
    </GradientStopCollection>
    <LinearGradientBrush x:Key="MyGlassBrushResource" StartPoint="0,0" EndPoint="1,1" Opacity="0" GradientStops="{StaticResource MyGlassGradientStopsResource}" />
    <LinearGradientBrush x:Key="GrayBlueGradientBrush" StartPoint="0,0" EndPoint="1,1">
        <GradientStop Color="DarkGray" Offset="0" />
        <GradientStop Color="#CCCCFF" Offset="0.5" />
        <GradientStop Color="DarkGray" Offset="1" />
    </LinearGradientBrush>
<!-- Button1の始まり -->
    <Style TargetType="{x:Type Button}" x:Key="ButtonStyle">
        <Setter Property="Background" Value="{StaticResource GrayBlueGradientBrush}" />
        <Setter Property="Width" Value="80" />
        <Setter Property="Margin" Value="10" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid Width="{TemplateBinding Width}"
                            Height="{TemplateBinding Height}" ClipToBounds="True">
                        <!-- Outer Rectangle with rounded corners. -->
                        <Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"
                                    VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"
                                    RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />

                        <!-- Inner Rectangle with rounded corners. -->
                        <Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"
                                    VerticalAlignment="Stretch" Stroke="Transparent"
                                    StrokeThickness="20" Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20" />
                        <!-- Glass Rectangle -->
                        <Rectangle x:Name="glassCube" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                                       StrokeThickness="2" RadiusX="10" RadiusY="10" Opacity="0" Fill="{StaticResource MyGlassBrushResource}"
                                       RenderTransformOrigin="0.5,0.5">
                            <Rectangle.Stroke>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                    <LinearGradientBrush.GradientStops>
                                        <GradientStop Offset="0.0" Color="LightBlue" />
                                        <GradientStop Offset="1.0" Color="Gray" />
                                    </LinearGradientBrush.GradientStops>
                                </LinearGradientBrush>
                            </Rectangle.Stroke>
                            <Rectangle.RenderTransform>
                                <TransformGroup>
                                    <ScaleTransform />
                                    <RotateTransform />
                                </TransformGroup>
                            </Rectangle.RenderTransform>
                            <Rectangle.BitmapEffect>
                                <BevelBitmapEffect />
                            </Rectangle.BitmapEffect>
                        </Rectangle>
                        <!-- Present Text of the button. -->
                        <DockPanel Name="myContentPresenterDockPanel">
                            <ContentPresenter x:Name="myContentPresenter" Margin="20" Content="{TemplateBinding  Content}" TextBlock.Foreground="Black" />
                        </DockPanel>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property ="Rectangle.Stroke" TargetName="outerRectangle" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                            <!-- Sets the glass opacity to 1, therefore, the           glass "appears" when user mouses over it. -->
                            <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />
                            <!-- Makes the text slightly blurry as though you           were looking at it through blurry glass. -->
                            <Setter Property="ContentPresenter.BitmapEffect" TargetName="myContentPresenter">
                                <Setter.Value>
                                    <BlurBitmapEffect Radius="1" />
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <Trigger Property="IsFocused" Value="true">
                            <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />
                            <Setter Property="Rectangle.Stroke" TargetName="outerRectangle" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                            <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />
                        </Trigger>
                        <!-- Animations that start when mouse enters and leaves button. -->
                        <EventTrigger RoutedEvent="Mouse.MouseEnter">
                            <EventTrigger.Actions>
                                <BeginStoryboard Name="mouseEnterBeginStoryboard">
                                    <Storyboard>
                                        <!-- This animation makes the glass rectangle shrink in the X direction. -->
                                        <DoubleAnimation Storyboard.TargetName="glassCube" 
                                                             Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" By="-0.1" Duration="0:0:0.5" />
                                        <!-- This animation makes the glass rectangle shrink in the Y direction. -->
                                        <DoubleAnimation Storyboard.TargetName="glassCube"
                                                            Storyboard.TargetProperty="(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
                                                            By="-0.1" Duration="0:0:0.5" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger.Actions>
                        </EventTrigger>
                        <EventTrigger RoutedEvent="Mouse.MouseLeave">
                            <EventTrigger.Actions>
                                <!-- Stopping the storyboard sets all animated properties back to default. -->
                                <StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard" />
                            </EventTrigger.Actions>
                        </EventTrigger>
                        <!-- Animation fires when button is clicked, causing glass to spin.  -->
                        <EventTrigger RoutedEvent="Button.Click">
                            <EventTrigger.Actions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="glassCube" 
                                                             Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)"
                                                             By="360" Duration="0:0:0.5" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger.Actions>
                        </EventTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
<!-- Button1の終わり -->

<!-- Button2の始まり -->
    <Style TargetType="Button" x:Key="CustomButton" >
        <Setter Property="Margin" Value="10" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid Width="{TemplateBinding Width}"
                            Height="{TemplateBinding Height}" ClipToBounds="True">
                        <Ellipse Width="100" Height="100">
                        <Ellipse.Fill>
                            <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                <GradientStop Offset="0" Color="Blue"/>
                                <GradientStop Offset="1" Color="Red"/>
                            </LinearGradientBrush>
                        </Ellipse.Fill>
                    </Ellipse>
                    <!-- Contentの中身をTemplateの中に埋め込むために以下が必要 -->
                        <DockPanel Name="myContentPresenterDockPanel1">
                            <ContentPresenter x:Name="myContentPresenter1" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding  Content}" TextBlock.Foreground="White" />
                        </DockPanel>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
<!-- Button2の終わり-->
</ResourceDictionary>

重要なポイント

Dictonary1.xamlでButtonタイプを継承し、新しくButtonSyleを定義します。

<Style TargetType="{x:Type Button}" x:Key="ButtonStyle">

ボタンに機能を持たせるには、ControlTemplateの下に記述する必要があります。


<ControlTemplate>
             <ControlTemplate.Trigger>
                <EventTrigger>
                     -----------
                </EventTrigger>
             </ControlTemplate.Trigger>
</ControlTemplate>

上記のDictionary1.xamlで記述したButtonStyle(Button1用)のデザインを引継ぎ、MainWindow.xamlで利用する。利用するには、Style="{StaticResource ****}" を使う。

<Button Style="{StaticResource ButtonStyle}" Content="Button1"/>
MainWindow.xaml
<Window x:Class="WpfApp5.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:local="clr-namespace:WpfApp5"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Background="Black">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <StackPanel HorizontalAlignment="Left">
        <Button Style="{StaticResource ButtonStyle}" Content="Button1"/>
        <Button Style="{StaticResource CustomButton}" Content="Button2"/>
        <Button Content="Button3"/>
    </StackPanel>
</Window>

最後に

今回の記事では、ボタンのカスタマイズだったので、xamlのみの変更修正です。
コードビハインドであるMainWindow.xaml.csには、デフォルトの内容です。

0
2
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
0
2