WPF の TextBox にはプレースホルダーを表示する機能がありません。あ、プレースホルダーっていうのは、WPF で以前 Watermark って呼んでいたやつです。HTML5 の影響で、プレースホルダーなんて格好つけて呼ぶようになってしまいました。
WPF がベータ版のときは WatermarkedTextBox っていうコントロールがあったんですが、機能が TextBox に統合されるという理由で廃止されました。でも .NET Framework 4 の TextBox にその機能はまだ見当たりません。私が見逃してるだけ?
TextBox にプレースホルダーを表示する方法は、Microsoft が運営する CodeRecipe で紹介されています。
でも、毎回 TextBlock に TextBox を重ねて半透明にするのは面倒ですね。
私は面倒くさがりなので、プレースホルダーを表示する添付ビヘイビアを作ってみました。
// プレースホルダーを表示する添付ビヘイビア public static class PlaceHolderBehavior { // プレースホルダーとして表示するテキスト public static readonly DependencyProperty PlaceHolderTextProperty = DependencyProperty.RegisterAttached( "PlaceHolderText", typeof(string), typeof(PlaceHolderBehavior), new PropertyMetadata(null, OnPlaceHolderChanged)); 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); } } } private static TextChangedEventHandler CreateEventHandler(string placeHolder) { // TextChanged イベントをハンドルし、TextBox が未入力のときだけ // プレースホルダーを表示するようにする。 return (sender, e) => { // 背景に TextBlock を描画する VisualBrush を使って // プレースホルダーを実現 var textBox = (TextBox)sender; if (string.IsNullOrEmpty(textBox.Text)) { textBox.Background = CreateVisualBrush(placeHolder); } else { textBox.Background = new SolidColorBrush(Colors.Transparent); } }; } private static VisualBrush CreateVisualBrush(string placeHolder) { var visual = new Label() { Content = placeHolder, Padding = new Thickness(5, 1, 1, 1), Foreground = new SolidColorBrush(Colors.LightGray), HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center, }; return new VisualBrush(visual) { Stretch = Stretch.None, TileMode = TileMode.None, AlignmentX = AlignmentX.Left, AlignmentY = AlignmentY.Center, }; } public static void SetPlaceHolderText(TextBox textBox, string placeHolder) { textBox.SetValue(PlaceHolderTextProperty, placeHolder); } public static string GetPlaceHolderText(TextBox textBox) { return textBox.GetValue(PlaceHolderTextProperty) as string; } }
VisualBrush を使って、TextBox の背景に TextBlock を描画しているところがポイント。
使い方はこんな感じです。
<Window x:Class="PlaceHolderSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:PlaceHolderSample" Title="MainWindow" Height="350" Width="525"> <Canvas> <TextBox x:Name="_nameTextBox" Canvas.Left="30" Canvas.Top="30" Width="200" local:PlaceHolderBehavior.PlaceHolderText="名前"/> </Canvas> </Window>
実行すると、TextBox が未入力のときにプレースホルダーが表示されます。
文字列を入力すると、プレースホルダーは消えます。
即興で作りましたが、TextBox にプレースホルダー機能が付くまでのつなぎとしては十分じゃないかな。