View内のUI操作のみでコントロールのプロパティの値を変更する

自前クラスのBooleanのプロパティをView内のUI操作だけで変更したかったので作ったActionのメモ

using System;
using System.Reflection;
using System.Windows;
using System.Windows.Interactivity;

namespace ToggleBoolPropertySample
{
    /// <summary>
    /// Booleanプロパティの値を切り替えるアクション
    /// </summary>
    public class ToggleBoolPropertyAction : TargetedTriggerAction<DependencyObject>
    {
        protected override void Invoke(object parameter)
        {
            //プロパティおよび変更対象のエレメントが取得できていれば
            if (Target != null && PropertyName != null)
            {
                //プロパティ情報を取得
                Type t = Target.GetType();
                PropertyInfo propertyInfo = t.GetProperty(PropertyName);

                //プロパティタイプがboolの場合の処理
                if (propertyInfo != null && propertyInfo.PropertyType == typeof(bool))
                {
                    var currentVal = (bool)propertyInfo.GetValue(Target, null);
                    var newValue = currentVal ? false : true;
                    propertyInfo.SetValue(Target, newValue, null);
                }
                //プロパティタイプがbool?の場合の処理
                else if(propertyInfo != null && propertyInfo.PropertyType == typeof(bool?))
                {
                    var currentVal = (bool?)propertyInfo.GetValue(Target, null);

                    //値がnullの場合は何もしない
                    if (currentVal == null)
                    {
                        return;
                    }

                    var newValue = currentVal == true ? false : true;
                    propertyInfo.SetValue(Target, newValue, null);
                }
            }
        }

        #region PropertyName Dependency Property
        public static readonly DependencyProperty PropertyNameProperty =
            DependencyProperty.Register("PropertyName", typeof(string), typeof(ToggleBoolPropertyAction), new PropertyMetadata(null));

        /// <summary>
        /// 変更対象のプロパティ名
        /// </summary>
        public string PropertyName
        {
            get
            {
                return (string)this.GetValue(PropertyNameProperty);
            }

            set
            {
                this.SetValue(PropertyNameProperty, value);
            }
        }
        #endregion
    }
}

使い方:

<Window x:Class="ToggleBoolPropertySample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:local="clr-namespace:ToggleBoolPropertySample"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel Orientation="Vertical">
            <CheckBox x:Name="TestCheckBox" Content="チェックボックス" IsChecked="True" Height="25" Width="100" Margin="30" />
            <Button x:Name="TestCheckButton" Content="ボタン" IsEnabled="True" Height="25" Width="100" Margin="30" />
            <Rectangle Width="100" Height="100" Margin="30" Fill="Aqua">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseEnter">
                        <local:ToggleBoolPropertyAction TargetName="TestCheckBox" PropertyName="IsChecked" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeave">
                        <local:ToggleBoolPropertyAction TargetName="TestCheckBox" PropertyName="IsChecked" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseEnter">
                        <local:ToggleBoolPropertyAction TargetName="TestCheckButton" PropertyName="IsEnabled" />
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeave">
                        <local:ToggleBoolPropertyAction TargetName="TestCheckButton" PropertyName="IsEnabled" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Rectangle>
        </StackPanel>
    </Grid>
</Window>

マウスがRectangleの外の場合:
f:id:chorusde:20121214025242p:plain

マウスがRectangleの中の場合:
f:id:chorusde:20121214025311p:plain

TargetedTriggerAction.Invokeの部分をいじればいろんなプロパティを変更できます(していいのか?)。