MENU

blog
スタッフブログ

dot
WPFでTextBoxにPlaceHolderを表示する
技術

WPFでTextBoxにPlaceHolderを表示する

こんにちは!ソリューションセクションの日野です

弊社、開発に際して結構いろいろな言語を使用しています
私が使用した言語だけでもphp(laravel,cakePHP等)やC#、go言語と様々です

現在はC#でWPFを使ってアプリケーションを開発中です
WPFはWindowsアプリケーションより自由度が高く細かいデザインができるのが特徴です
ただ、自由度が高すぎで絶妙にやりたいことができない、やれるけどめっちゃ複雑。。。ということが多々あります

今回はWPFでTextBoxにPlaceHolderを表示したかったので拡張プロパティを作りました

最終的に以下のようになります

この「テスト」を表示するために拡張プロパティが必要です
ざっくり説明すると拡張プロパティのPlaceHolderに設定された文言をTextBoxの背景にするって感じになってます

ソースコード

PlaceholderTextBox.xaml

プレースホルダ―を表示するTextBoxの拡張クラスのソースです

class PlaceholderTextBox : TextBox
{
    //プレースホルダ―用のプロパティを追加
    public static readonly DependencyProperty PlaceholderProperty =
        DependencyProperty.Register("Placeholder", typeof(string), 
                  typeof(PlaceholderTextBox), new PropertyMetadata(null, OnPlaceHolderChanged));
 
    private string _placeholder = string.Empty;
    /// <summary>
    /// プレースホルダーのプロパティを設定
    /// </summary>
    public string Placeholder
    {
        get
        {
            return _placeholder;
        }
        set
        {
            _placeholder = value;
        }
    }
 
    /// <summary>
    /// プレースホルダ―が変更されたときの変更
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private static void OnPlaceHolderChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var textBox = sender as TextBox;
        if (textBox == null)
        {
            return;
        }
        //設定された文言をプレースホルダにいれます
        var placeHolder = e.NewValue as string;
        var handler = CreateEventHandler(placeHolder);
        if (string.IsNullOrEmpty(placeHolder))
        {
            textBox.TextChanged -= handler;
        }
        else
        {
            textBox.TextChanged += handler;
            if (string.IsNullOrEmpty(textBox.Text))
            {
                //プレースホルダ―の背景に文字列を設定します
                textBox.Background = CreateVisualBrush(placeHolder);
            }
        }
    }

    /// <summary>
    /// textChangedイベント作成
    /// </summary>
    /// <param name="placeHolder"></param>
    /// <returns></returns>
    private static TextChangedEventHandler CreateEventHandler(string placeHolder)
    {
        return (sender, e) =>
        {
            var textBox = (TextBox)sender;
            if (string.IsNullOrEmpty(textBox.Text))
            {
                //Textが入力されていなければプレースホルダーを表示します
                textBox.Background = CreateVisualBrush(placeHolder);
            }
            else
            {
                //Textが入力されたときに背景を真っ白にします
                textBox.Background = new SolidColorBrush(Colors.White);
            }
        };
    }

    /// <summary>
    /// 背景色を変更します
    /// </summary>
    /// <param name="placeHolder">PlaceHolderに設定された文言</param>
    /// <returns>塗りつぶしの色を返します</returns>
    private static VisualBrush CreateVisualBrush(string placeHolder)
    {
        //入力された文言でTextBlockを生成します
        var visual = new TextBlock()
        {
            Text = placeHolder,
            Padding = new Thickness(2, 1, 500, 1),
            Foreground = new SolidColorBrush(Colors.LightGray),
            HorizontalAlignment = HorizontalAlignment.Stretch,
            VerticalAlignment = VerticalAlignment.Stretch,
            Background = new SolidColorBrush(Colors.White)
        };
        //生成された塗りつぶしの色を返します
        return new VisualBrush(visual)
        {
            Stretch = Stretch.None,
            TileMode = TileMode.None,
            AlignmentX = AlignmentX.Left,
            AlignmentY = AlignmentY.Center, 
        };
    }
 
    /// <summary>
    /// プレースホルダーをsetしたときの処理
    /// </summary>
    /// <param name="textbox">自分自身のTextBox</param>
    /// <param name="placeHolder">PlaceHolderに設定された文言</param>
    private static void SetPlaceHolderText(TextBox textbox, string placeHolder)
    {
        textbox.SetValue(PlaceholderProperty, placeHolder);
    }

    /// <summary>
    /// プレースホルダー取得処理
    /// </summary>
    /// <param name="textBox"></param>
    /// <returns>プレースホルダーで設定された文字を返します</returns>
    public static string GetPlaceHolderText(TextBox textBox)
    {
        return textBox.GetValue(PlaceholderProperty) as string;
    }
}

Window.xaml

上記の拡張クラスをWindowのXamlで呼びます

<local:PlaceholderTextBox Placeholder="テスト" Width="100" />
<local:PlaceholderTextBox Placeholder="テスト" Margin="0,50,0,0" Width="100" />

これでプレースホルダ―を表示できました!
HTMLであればInputタグで普通にPlaceholder属性が使用できるので
WPFでもこれくらい簡単にしてほしいところですね

今回はこの辺で!
それでは!!

dot
dot
PAGETOP