読者です 読者をやめる 読者になる 読者になる

SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

Windows8でWPFのトグルボタン表示がおかしい

Windows8環境のWPFアプリでは、ToggleButtonを押しても、トグル状態の押し込んだ表示が行われません。

テストコード

ToggleButtonを配置しただけの、シンプルな画面です。
ボタンをクリックしても、トグル状態の表示が行われません。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ToggleButton Content="ToggleButton"
                      HorizontalAlignment="Left"
                      VerticalAlignment="Top"
                      Margin="20"/>
    </Grid>
</Window>

Snoopで、このToggleButtonのIsCheckedプロパティを見てみると、
IsCheckedの値はちゃんと変わっています。
トグル時の表示の変化が無いようです。



Win8のToggleButtonのコントロールテンプレート

参考までに、Win8&VS2012の環境で「テンプレートの編集⇒コピーして編集」を実行して、ToggleButtonのControlTemplateを出力してみました。

ToggleButtonのテンプレート
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style x:Key="ToggleButtonStyle1" TargetType="{x:Type ToggleButton}">
            <Setter Property="FocusVisualStyle">
                <Setter.Value>
                    <Style>
                        <Setter Property="Control.Template">
                            <Setter.Value>
                                <ControlTemplate>
                                    <Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </Setter.Value>
            </Setter>
            <Setter Property="Background" Value="#FFDDDDDD"/>
            <Setter Property="BorderBrush" Value="#FF707070"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Padding" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                            <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="Button.IsDefaulted" Value="True">
                                <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Background" TargetName="border" Value="#FFBEE6FD"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="#FF3C7FB1"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
                                <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <ToggleButton Content="ToggleButton"
                      HorizontalAlignment="Left"
                      VerticalAlignment="Top"
                      Margin="20" Style="{DynamicResource ToggleButtonStyle1}"/>
    </Grid>
</Window>

うーん、確かにこれじゃ、トグル時に表示が切り替わらないよなぁ。。。
↑のテンプレートのTriggerに、以下の内容を追加すれば、Win8環境ではトグル表示がされるようになります。

<Trigger Property="IsChecked" Value="True">
    <Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
    <Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
</Trigger>

しかし、こんな風にControlTemplateを書いてしまうと、どのOSで動かしてもこのWin8風デザインの表示になってしまう。
ちょっと、手軽に対処する方法が思いつかない。。。


ToggleButtonは、何か他のコントロールを作成する時のベースコントロールとするようなものなので、あまり使うことはないかもしれないけど、
Win8でToggleButtonを使うときには注意が必要ですね。