質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.34%

マウスホバー時のプロパティトリガーの動作について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,649

score 6

マウスホバー時のプロパティトリガーの動作について教えて下さい。

まず以下のの通りXAMLでLabelのStyleを定義します。

<Window.Resources>
        <Style TargetType="{x:Type Label}">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="FontSize" Value="30"/>
                    <Setter Property="Foreground" Value="Red"/>
                    <Setter Property="Background" Value="Yellow"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Label x:Name="MyLabel" Content="Mouse hover over a Label"
               HorizontalAlignment="Center"
               VerticalAlignment="Center"/>
    </Grid>


このコードの場合はマウスホバー時にFontSize、Foreground、Background全て
正しく変化します。

しかし諸々の理由でコードビハインドからBackgroundプロパティの色をYellow以外に
変える必要があります。例えば上記のXAMLに対して以下の通りコンストラクター
の中でBackgroundプロパティをWhiteに設定します。

public MainWindow()
{
    InitializeComponent();
    MyLabel.Background = Brushes.White;
}

このようにするとマウスホバー時のBackgroundがWhiteになってしまいます。
望む動作はStyleで定義した通りのYellowになって欲しいのですが方法がわかりません。

何か良い方法がありましたらご教示ください。

実際に実現したいことはLabelコントロールではなくCalendarコントロールです。
改めてXAMLの抜粋を記載致します。複雑になるため動作に関係のないイベントハンドラ
は省略しております。

<Viewbox>
<Calendar x:Name="MyCalendar">
    <Calendar.CalendarDayButtonStyle>
        <Style TargetType="{x:Type CalendarDayButton}">                    
            <Setter Property="Template">
                <Setter.Value>
                     <ControlTemplate TargetType="{x:Type CalendarDayButton}">
                         <Border x:Name="MyHoverButtonBorder" BorderThickness="0.1">
                              <ContentPresenter/>
                         </Border>
                         <ControlTemplate.Triggers>
                         <!-- マウスオーバー -->
                             <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="MyHoverButtonBorder" Property="BorderBrush" Value="Pink" />
                                <Setter TargetName="MyHoverButtonBorder" Property="Background" Value="Pink" />
                                <Setter Property="Foreground" Value="White" />
                             </Trigger>
                         </ControlTemplate.Triggers>
                     </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Calendar.CalendarDayButtonStyle>
</Calendar>
</Viewbox>


日をクリックすると背景をグリーン色にしているのですが、事情により
月が変わるたびに全ての日の背景を一度ホワイト色でクリアする必要があります。
クリアはコードビハインドで行っていますが、そうするとマウスホバー時に上記の
XAMLで指定したピンク色にはならずホワイト色のままになってしまいます。
ホワイト色でクリアした後でも個々の日をマウスホバー時にピンク色にすることは
可能でしょうか?

上手く動作したCalendarDayButtonの背景をクリアするコードは以下の通りです。

void AllDaysClear(CalendarDayButton[] days)
{
    foreach (var day in days)
    {
        var border = day.Children<Border>().FirstOrDefault();
        if (border != null)
        {
            border.BorderBrush = Brushes.Black;
            //border.Background = Brushes.White; //期待通りの動作をしない
            border.ClearValue(BackgroundProperty); //期待通りの動作をする
            day.IsEnabled = true;
        }
    }
}


Childrenメソッドは「じんぐる様」の下記サイトのコードを拝借し検証しました。
https://blog.xin9le.net/entry/2013/10/29/222336

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Zuishin

    2019/10/30 13:32

    ControlTemplate は私の回答に書いたものです。解決法は知っていますが、無視された上でこのような扱いをされたのでは回答する気がなくなります。

    キャンセル

  • bep

    2019/10/30 13:52

    大変失礼しました。
    ご回答頂きましたお二人への回答を書くのに時間がかかってしまいすみませんでした。

    キャンセル

回答 2

checkベストアンサー

0

依存関係プロパティ値の優先順位
https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/advanced/dependency-property-value-precedence

をみた感じでは、

ローカル プロパティ セットは最高の優先順位で設定されます

とありますので、他のトリガーなどでは優先順位が低く、適用されないんだろうなと思います。

どういう解決策があるのかはわかりませんが、

例えばラベルの背景を変えるのではなくて、

  • ラベルの装飾として置いたボーダーの背景色
  • ラベルとレイヤーを組んだ別のコントロールの背景色

をコードビハインドで変えるという手が使えるのかなと思いました。

ただ、これだけだと実行時、マウスオーバーで四角の上に別の四角を描画するという形になり、描画範囲に誤差が出るとゴミが表示される気がするのでUseLayoutRounding="True"を入れてごまかしてあります。

<Window x:Class="WpfApplication1.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:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        UseLayoutRounding="True">

    <Window.Resources>
        <Style TargetType="{x:Type Label}">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="FontSize" Value="30"/>
                    <Setter Property="Foreground" Value="Red"/>
                    <Setter Property="Background" Value="Yellow"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

    <Grid>
        <Border x:Name="MyLabelBorder"
                HorizontalAlignment="Center"
                VerticalAlignment="Center">
            <Label x:Name="MyLabel" Content="Mouse hover over a Label" />
        </Border>
    </Grid>
</Window>
namespace WpfApplication1
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            MyLabelBorder.Background = Brushes.Red;
        }
    }
}

イメージ説明

※自分はあんまりWPFは詳しくないので、もうちょっと上手い方法がありそうです。


日をクリックすると背景をグリーン色にしているのですが、事情により
月が変わるたびに全ての日の背景を一度ホワイト色でクリアする必要があります。
クリアはコードビハインドで行っていますが、そうするとマウスホバー時に上記の
XAMLで指定したピンク色にはならずホワイト色のままになってしまいます。
ホワイト色でクリアした後でも個々の日をマウスホバー時にピンク色にすることは
可能でしょうか? 

えーと

日をクリックすると背景をグリーン色にしている

もコードビハインドで、

全ての日の背景を一度ホワイト色でクリアする

もコードビハインドでBrushes.Whiteか何かを何かに代入しているのかなと思いますが、
クリアをBrushes.Whiteではなくnullを代入してみるとどうでしょう?


更に追記:
最初のラベルのサンプルで試していましたが

MyLabel.Background = Brushes.Red;

としたあと、

MyLabel.ClearValue(BackgroundProperty);

とすれば、添付プロパティの内容をクリアできるようです。
nullではなく、こちらを使ってみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/30 15:42

    あ、nullじゃだめでした、すみません。

    キャンセル

  • 2019/10/30 15:49

    ClearValue案を追記しました(^_^;何度もすみません。

    キャンセル

  • 2019/10/30 16:06

    お返事ありがとうございます。

    コードビハインド内で以下の方法を実行したところ期待通り背景色
    が変わりました。
    MyLabel.ClearValue(BackgroundProperty);

    どうもありがとうございました。

    キャンセル

0

Style.TriggersとControlTemplate.Triggersの違い - プログラマーな日々

ControlTemplate.Triggers を使ってみてください。

<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ControlTemplate TargetType="{x:Type Label}" x:Key="labelTemplate">
            <Border Background="{TemplateBinding Background}" x:Name="border">
                <ContentPresenter/>
            </Border>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="FontSize" Value="30"/>
                    <Setter Property="Foreground" Value="Red"/>
                    <Setter TargetName="border" Property="Background" Value="Yellow"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Window.Resources>
    <Grid>
        <Label x:Name="MyLabel" Content="Mouse hover over a Label"
            Template="{StaticResource labelTemplate}"
            HorizontalAlignment="Center"
            VerticalAlignment="Center">
        </Label>
    </Grid>
</Window>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/30 14:26

    ご回答ありがとうございます。

    Background="{TemplateBinding Background}"を追記してみたのですが
    背景色はホワイト色のままでした。コードビハインドに問題があるかもしれ
    ませんので、そちらを再検討してみます。

    キャンセル

  • 2019/10/30 14:29 編集

    バインド先が違うだけのこと。takabosoft さんの方法でもできるので、そっちを採用して質問のコードを書き直してください。

    キャンセル

  • 2019/10/30 16:05

    お返事ありがとうございます。

    takabosoft さんから頂きました以下の方法でBorderコントロールのBackgroundプロパティを
    クリアしたところ上手くいきました。
    MyLabel.ClearValue(BackgroundProperty);
    コードビハインドを追記しておきます。

    どうもありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る