2010年4月14日水曜日

メモ 【修正あり】3タイプのTriggerのサンプル

WPFで凝った表示をしようとすると、Triggerを使うことがよくありますが、
使える組み合わせが限られたり、私はよくこんがらがります。
そこでよく使う3パターンを自分用にメモしておきます。
※もしかしたらもっと単純なやり方があるかもしれません

■パターン1
ある表示要素のプロパティが変わったときに、その要素自体の他のプロパティを変える
例:Borderの上にマウスがのったら、Border自体の色を変える

■パターン2
ある表示要素のプロパティが変わったときに、その要素の中身の他の要素のプロパティを変える
例:Borderの上にマウスがのったら、内側に非表示にしておいたボタンを表示する

■パターン3
表示要素と全く関係ないデータが変わったときに、表示要素のプロパティを変える
例:内部でエラーがおきたら、背景の色を変える

まずパターン3のためのデータのクラスを書きます。
値の変更を検出するためにINotifyPropertyChangedインターフェイスを実装します


 class Model : INotifyPropertyChanged {
  private bool _isOn;
  public bool IsOn {
   get {
    return _isOn;
   }
   set {
    if (_isOn != value) {
     _isOn = value;
     var handler = PropertyChanged;
     if (handler != null) {
      handler(this, new PropertyChangedEventArgs("IsOn"));
     }
    }
   }
  }

  public event PropertyChangedEventHandler PropertyChanged;
 }



以下に3パターンを含んだXamlを示します。


<Window x:Class="TriggerSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:TriggerSample"
        Title="MainWindow" Height="350" Width="525">
 <!--3タイプのTriggerを使ってみたサンプル-->
 
 <Window.DataContext>
  <local:Model x:Name="data"/>
 </Window.DataContext>

 <StackPanel>
  <!--自分自身のプロパティに従って、他のプロパティを変更する-->
  <Border BorderBrush="Green" BorderThickness="2" Margin="5">
   <TextBlock>Borderの上にマウスを置いたらBorderの色が変わる</TextBlock>
   <Border.Style>
    <Style TargetType="{x:Type Border}">
     <Setter Property="Background" Value="Yellow"/>
     <Style.Triggers>
      <Trigger Property="IsMouseOver" Value="True">
       <Setter Property="Background" Value="Red"/>
      </Trigger>
     </Style.Triggers>
    </Style>
   </Border.Style>
  </Border>

  <!--外のプロパティに従って内側のプロパティを変更する-->
  <Border Background="LightBlue" BorderBrush="Red" BorderThickness="3" Name="_outer">
   <StackPanel Orientation="Horizontal">
    <TextBlock>外側のBorderにマウスを置いたら内側のBorderの色が変わる</TextBlock>
    <Border BorderBrush="Black" BorderThickness="3" CornerRadius="3">
     <TextBlock>内側のBorder</TextBlock>
     <Border.Style>
      <Style TargetType="{x:Type Border}">
       <Style.Triggers>
        <DataTrigger Binding="{Binding ElementName=_outer, Path=IsMouseOver}" Value="True">
         <Setter Property="Background" Value="Blue"/>
        </DataTrigger>
       </Style.Triggers>
      </Style>
     </Border.Style>
    </Border>
   </StackPanel>
  </Border>
  
  <!--(Borderに関係ない)データの値に従ってプロパティを変更する-->
  <Border BorderBrush="Pink" BorderThickness="3" Margin="5" Name="border">
   <TextBlock>データの値でBorderの色が変わる</TextBlock>
   <Border.Style>
    <Style TargetType="{x:Type Border}">
     <Setter Property="Background" Value="Orange"/>
     <Style.Triggers>
      <DataTrigger Binding="{Binding ElementName=data, Path=IsOn}" Value="True">
       <Setter Property="Background" Value="DarkGray"/>
      </DataTrigger>
     </Style.Triggers>
    </Style>
   </Border.Style>
  </Border>
  
  <CheckBox IsChecked="{Binding ElementName=data, Path=IsOn, Mode=TwoWay}">ここを押してデータを変える</CheckBox>

 </StackPanel>
</Window>




結果画像

2 件のコメント:

  1. より簡単な書き方を発見したので、
    投稿後修正しました。

    返信削除
  2. なんか修正したらコードの色が反映されなくなってしまいました。。

    返信削除