WPFでTextBoxがフォーカスを得たときに背景色を変える Attached Property

コンピュータ

Attached Properyの使い方を確認のためのサンプルコードです。

起動イメージ

TextBoxがフォーカス得た状態


FocusHelper.cs

// TextBox や Button などの Control に、フォーカスを得たときに背景色を変える Attached Property を定義するクラス
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace AttachedPropertyDemo;

public static class FocusHelper	// static クラスにすることで、インスタンス化を防止
{
    // Attached Property 登録
    public static readonly DependencyProperty IsHighlightProperty =
        DependencyProperty.RegisterAttached(					// RegisterAttached メソッドで、プロパティを登録
            "IsHighlight",										// プロパティ名
            typeof(bool),										// プロパティの型
            typeof(FocusHelper),								// 所有するクラスの型
            new PropertyMetadata(false, OnIsHighlightChanged));	// デフォルト値と値変更時のコールバックを指定

    // GetValue メソッドで、プロパティの値を取得
    public static bool GetIsHighlight(DependencyObject obj)
        => (bool)obj.GetValue(IsHighlightProperty);

    // SetValue メソッドで、プロパティの値を設定
    public static void SetIsHighlight(DependencyObject obj, bool value)
        => obj.SetValue(IsHighlightProperty, value);

    // 値変更時のコールバック(プロパティの値が変更されたときに呼び出されるメソッド)
    private static void OnIsHighlightChanged(
        DependencyObject d,						// プロパティが設定されたオブジェクト
        DependencyPropertyChangedEventArgs e)	// プロパティの値が変更されたときのイベント引数
    {
        if (d is not Control control)	// プロパティが設定されたオブジェクトが Control 型でない場合は、
            return;						// 何もせずに終了

        if ((bool)e.NewValue)	// プロパティの新しい値が true の場合は、
        {
            control.GotFocus += Control_GotFocus;	// GotFocus イベントにハンドラーを追加
            control.LostFocus += Control_LostFocus;	// LostFocus イベントにハンドラーを追加
        }
        else
        {
            control.GotFocus -= Control_GotFocus;	// GotFocus イベントからハンドラーを削除
            control.LostFocus -= Control_LostFocus;	// LostFocus イベントからハンドラーを削除
        }
    }

	// フォーカスを得たときのイベントハンドラー
    private static void Control_GotFocus(object sender, RoutedEventArgs e)
    {
        if (sender is Control c)
            c.Background = Brushes.LightYellow;
    }

	// フォーカスを失ったときのイベントハンドラー
    private static void Control_LostFocus(object sender, RoutedEventArgs e)
    {
        if (sender is Control c)
            c.ClearValue(Control.BackgroundProperty);
    }
}

MainWindow.xaml

<Window x:Class="AttachedPropertyDemo.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:AttachedPropertyDemo"
        mc:Ignorable="d"
        Title="AttachedProperty Sample"
        Height="200"
        Width="300">
    <StackPanel Margin="20">
        <TextBox
            Height="30"
            local:FocusHelper.IsHighlight="True" <!-- プロパティIsHighlightを生やしている -->
            Text="フォーカスすると色が変わります"/>

        <TextBox
            Height="30"
            Margin="0,10,0,0"
            Text="これは通常のTextBox"/>
    </StackPanel>
</Window>

使う側のコード


XAMLで使うIsHighlightをFocusHelperクラスのプロパティとして定義しています。

プロパティをTrueにすると、GotFocusLostFocusイベントハンドラがアタッチされ、Falseにするとデタッチされます。

Attached Propertyの振る舞いとしては以上となります。

コメント