泥庭

2011年1月6日

カスタムコントロールとGeneric.xaml(Styleその③)

Filed under: WPF — タグ: , , — yone64 @ 11:01 PM

年が明けてしまいました。今年はもっと情報発信ができるといいなぁ。

VisualStudio2010でWPFのCustomControlLibraryを作成すると、Themesフォルダ内にGeneric.xamlというファイルが作成されます。
image

このGeneric.xamlファイルでも、Styleを使用してコントロールのTemplate等を定義します。

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomControlLibrary">
    <Style TargetType="{x:Type local:CustomControl1}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">

                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

基本は今までのStyleと同じですが、一点注意事項があります。

ここで指定したTargetTypeは、Classの型を基準に適用されるのではなく、

FraeworkElement.DefaultStyleKeyPropertyに指定された型をベースに適用されます。

そのため、カスタムコントロールの定義には、staticコンストラクタに次のような指定があります。

static CustomControl1()
{
    DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
}

この定義を忘れると、StyleTargetTypeが型に一致していても、Styleが適用されることはありません。

2010年12月22日

Style(その②)

Filed under: WPF — タグ: , — yone64 @ 12:24 AM

前回に引き続きStyleの話

①Default設定について
Styleタグに明示的にKeyを指定しない場合は、TragetTypeと同じ値が設定されます。
つまり

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

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

は、同じ意味です。

また、FrameworkElementクラスのStyleプロパティーは、明示的に指定しない場合、そのクラスのTypeが設定されます。
つまり

<Button Name="button2" Content="ボタン2" />

<Button Name="button2" Content="ボタン2" Style="{StaticResource ResourceKey={x:Type Button}}" />


は同じ意味です。

総合すると、明示的にKeyを指定しないStyleは、Resourceを明示的に指定しないすべてのコントロールに適用されることになります。

②Style VS プロパティー
プロパティーに値が設定されたコントロールは、Styleの値は設定されません。次の場合、FontSizeはプロパティーに直接指定した「20」になります。

<Button Content="ボタン3" FontSize="20">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="FontSize" Value="10"></Setter>
        </Style>
    </Button.Style>
</Button>

③Styleの継承
StyleタグのBaseOnプロパティーを指定することで、Styleを継承し拡張することが出来ます。

<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ResourceKey={x:Type Button}}">
    <Setter Property="FontSize" Value="20"/>
</Style>

まとめ
以上を踏まえて、次のXAMLは

<Window x:Class="StyleSample.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="350" Width="298" xmlns:my="clr-namespace:StyleSample">
    <Window.Resources>
        <Style TargetType="{x:Type Button}">
            <Setter Property="FontSize" Value="30"></Setter>
            <Setter Property="Foreground" Value="Red"></Setter>
        </Style>
        <Style x:Key="Button" TargetType="{x:Type Button}" BasedOn="{StaticResource ResourceKey={x:Type Button}}">
            <!-- プロパティーの上書き -->
            <Setter Property="Foreground" Value="Blue"/>
            <!-- プロパティーの追加 -->
            <Setter Property="LayoutTransform">
                <Setter.Value>
                    <TransformGroup>
                        <RotateTransform Angle="45"/>
                    </TransformGroup>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <StackPanel>
        <!-- 何も指定しない場合、デフォルトスタイルが適用される -->
        <Button Content="ぼたん"/>
        <!-- プロパティーに直接指定した場合は、プロパティーの値が優先 -->
        <Button Content="ぼたん1" FontSize="40"/>
        <!-- リソースを明示的に指定した場合、指定したスタイルが適用される -->
        <Button Content="ぼたん2" Style="{StaticResource ResourceKey=Button}"/>
        <!-- ボタンを継承したオリジナルクラスには適用されない -->
        <my:ButtonEx Content="Button"/>
        <!-- 明示的に指定すれば、適用される -->
        <my:ButtonEx Content="Button1" Style="{StaticResource ResourceKey={x:Type Button}}"/>
    </StackPanel>
</Window>

以下のような、UIになります。
image

2010年12月20日

Style

Filed under: WPF — タグ: — yone64 @ 12:37 AM

StyleってWPFの特徴の一つですよね。日頃何となく使っているStyleを気付いたことベースでまとめてみました。

Styleの基本。

FrameworkElementStyle型の依存性プロパティーを持っています。
このプロパティーを通して他の依存性プロパティーの値を設定することが出来ます。
例えば、次のxamlはStyleプロパティーを利用しFont関連のプロパティーを設定しています。

<Button Content="ぼたん" Name="button1">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="FontFamily" Value="Consolas"/>
            <Setter Property="FontSize" Value="15"/>
            <Setter Property="Foreground" Value="Blue"/>
        </Style>
    </Button.Style>
</Button>

は、以下と同じです。

<Button Content="ぼたん" Name="button1" FontFamily="Consolas" FontSize="15" Foreground="Blue" />

何がうれしいの?

Styleを使用しなくても、プロパティーの設定が出来るのであれば、Styleを使うメリットは何でしょう。
①Trigger
Style.TriggersにTriggerを設定することで条件付きでプロパティー値の変更が出来ます。
以下は、ボタンにマウスが乗ったときに文字を大きくするサンプルです。

<Button Content="ぼたん" Name="button1">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="FontFamily" Value="Consolas"/>
            <Setter Property="FontSize" Value="15"/>
            <Setter Property="Foreground" Value="Blue"/>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="FontSize" Value="30"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

②Resource
他のプロパティー同様、StyleもResourceに定義している物を利用することが出来ます。
つまり、複数のプロパティーと値のセットをStyleとしてResourceに登録しておくことで、複数のプロパティーを一括で設定することが出来ます。

(定義)

<Window.Resources>
    <Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Aqua"/>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="FontSize" Value="50"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

(適用)

<Button Name="button2" Content="ボタン2" Style="{StaticResource ResourceKey=ButtonStyle}" />

続く

WordPress.com Blog.