WPFのButtonにTemplateを適用すると部分的にクリック判定されない問題と解決策

WPF

WPFでButtonにTemplateを適用した際に部分的にクリックが判定されない問題に出くわして、解決するのに少し苦労したのでその問題と解決策を備忘録としてまとめます。

結構色々なサイトなどを調べてみましたがどうも同じ現象に遭遇してる人がいないようで(しょうもないからか)同じように困った人のために記録として残しておきます。

発生した問題

問題の簡単化のために以下のXAMLでWindow内にボタンを1つ配置します。

<Window.Resources>
  <!-- ボタンのスタイル -->
  <Style x:Key="ButtonTemp" TargetType="Button">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">
          <DockPanel LastChildFill="True">
            <Border Height="1" BorderThickness="1" BorderBrush="Red" DockPanel.Dock="Top" />
            <Border Height="1" BorderThickness="1" BorderBrush="Red" DockPanel.Dock="Bottom" />
            <ContentPresenter />
          </DockPanel>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</Window.Resources>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
  <!-- 問題が発生するボタン -->
  <Button Style="{StaticResource ButtonTemp}" Click="Button_Click" Width="150" Height="200">
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
      <Ellipse Width="100" Height="100" Fill="SkyBlue" />
      <TextBlock Text="Hoge" TextAlignment="Center" FontSize="24" Margin="0 20 0 0" />
    </StackPanel>
  </Button>
</StackPanel>

テンプレートではボタンの上下に赤い線を挿入し、ボタンには水色の円と適当な文字列を表示しています。

上記のウィンドウでは上の赤い線から下の赤い線まで(幅は赤い線と同じ幅)がボタンの領域となるので、その領域内であればクリックの判定が効いてほしいところです。

しかし実際には水色の円の領域と文字列の領域のみクリック判定が効いて、他の領域ではクリック判定が効きませんでした。

問題の解決策

色々と試したところボタン内(またはテンプレート内)の何も存在しない箇所(要素が存在しない、色の指定がないなど)はクリック判定が効かないようでした。

そのため、解決策としては「要素全体の背景色を指定する」「要素全体にまたがる要素を配置する」など、何もない領域を作らないことでクリック判定が効くようになりました。

上記のプログラムの場合には、背景色を変えたくないなどの要望がある場合でも「Background=”Transparent”」とすることで背景に透明が指定されクリックが効くようになります。

<Window.Resources>
  <!-- ボタンのスタイル -->
  <Style x:Key="ButtonTemp" TargetType="Button">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">
          <DockPanel LastChildFill="True" Background="Transparent">
            <Border Height="1" BorderThickness="1" BorderBrush="Red" DockPanel.Dock="Top" />
            <Border Height="1" BorderThickness="1" BorderBrush="Red" DockPanel.Dock="Bottom" />
            <ContentPresenter />
          </DockPanel>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</Window.Resources>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
  <!-- 問題が発生するボタン -->
  <Button Style="{StaticResource ButtonTemp}" Click="Button_Click" Width="150" Height="200">
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
      <Ellipse Width="100" Height="100" Fill="SkyBlue" />
      <TextBlock Text="Hoge" TextAlignment="Center" FontSize="24" Margin="0 20 0 0" />
    </StackPanel>
  </Button>
</StackPanel>

ちなみに、初めは<Setter>要素で背景色を指定していたのですが効いていないっぽかったので、Templateの要素内で背景色を指定したらたまたまうまくいきました。(<Setter>で背景色が指定できない原因はわかりません)

終わりに

WPFのButtonにTemplateを適用すると部分的にクリック判定されない問題と解決策についてまとめました。

自分自身結構ハマったので誰かの役に立てば幸いです。

この記事について誤っている点・不明な点などありましたらコメントまでお願いします。

コメント

タイトルとURLをコピーしました