特定の値以上だったら動作するTriggerを作る
WPFのTrigger、便利ですよね。
Styleを作るときに、特定の条件の時に表示を切り替えたり簡単にできて、非常に便利。
でも、ちょっと痒いとこに手が届かない。
Triggerだと、指定したプロパティが特定の値の場合に動作します。
なので、「指定したプロパティが○○以上だったら」みたいな条件を指定できません。
そんな時は、Converterを併用することで前述の動作を実装できます。
こんなコンバーターを用意しておくと、何かと便利だと思います。
public class IsGreaterThanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var v = System.Convert.ToDouble(value); var compareValue = double.Parse(parameter as string); return v > compareValue; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } public class IsLessThanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var v = System.Convert.ToDouble(value); var compareValue = double.Parse(parameter as string); return v < compareValue; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
※制限
ConverterParameterで条件に用いる数値を指定してます。
なので、この条件の数値はバインドすることができず、動的な条件を実現することはできません。
使用例1
スライダーのValueプロパティを、TextBlockのTextにバインドしています。
TextBlockのStyleでDataTriggerを設定し、
IsLessThanConverterを使って、Valueが0以下だったら、TextBlockの文字色が赤くなるようにしています。
MainWindow.xaml
<Window x:Class="WpfBaseTemplate1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfBaseTemplate1" Title="MainWindow" Width="400" Height="200"> <Window.Resources> <local:IsLessThanConverter x:Key="IsLessThanConverter" /> </Window.Resources> <Grid> <StackPanel Margin="50"> <TextBlock Margin="5" Text="{Binding Value, ElementName=sldValue, StringFormat=\{0:F2\}}"> <TextBlock.Style> <Style TargetType="{x:Type TextBlock}"> <Style.Triggers> <DataTrigger Binding="{Binding Value, Converter={StaticResource IsLessThanConverter}, ConverterParameter=0, ElementName=sldValue}" Value="True"> <Setter Property="Foreground" Value="Red" /> </DataTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock> <Slider x:Name="sldValue" Minimum="-10" /> </StackPanel> </Grid> </Window>
使用例2
今度は、DataContextに設定したVMのプロパティとバインドしてます。
ボタンを押すと、リストボックスの項目が増えていきますが、項目数が5個になったら、リストボックスの枠を赤くするようにDataTriggerの設定をしてます。
MainWindow.xaml
<Window x:Class="WpfBaseTemplate1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfBaseTemplate1" Title="MainWindow" Width="400" Height="300"> <Window.DataContext> <local:MainWindowViewModel /> </Window.DataContext> <Window.Resources> <local:IsGreaterThanConverter x:Key="IsGreaterThanConverter" /> </Window.Resources> <Grid> <ListBox HorizontalAlignment="Left" Margin="10" Width="158" ItemsSource="{Binding Items}"> <ListBox.Style> <Style TargetType="{x:Type ListBox}"> <Style.Triggers> <DataTrigger Binding="{Binding Items.Count, Converter={StaticResource IsGreaterThanConverter}, ConverterParameter=5}" Value="True"> <Setter Property="BorderBrush" Value="Red" /> </DataTrigger> </Style.Triggers> </Style> </ListBox.Style> </ListBox> <Button Content="Add" HorizontalAlignment="Left" Margin="173,10,0,0" VerticalAlignment="Top" Width="75" Command="{Binding AddCommand}"/> </Grid> </Window>
MainWindowViewModel.cs
class MainWindowViewModel : BindableBase { private ObservableCollection<string> items; public ObservableCollection<string> Items { get { return items; } set { this.SetProperty(ref this.items, value); } } public MainWindowViewModel() { this.Items = new ObservableCollection<string>(); } private RelayCommand addCommand; public RelayCommand AddCommand { get { return addCommand = addCommand ?? new RelayCommand(Add); } } private void Add() { this.Items.Add("hoge"); } }