背景イメージを使用してTextBoxの操作性を高める -Visualbrushを使う-


この図のように,TextBoxが空のときに機能および入力文字列の書式を表示すると親切です.
MSDN方法: TextBox へのウォーターマークの追加 | Microsoft Docsの方法はImageBrushを使用しています.これはBackgroundがDataContextに影響しないことを利用して,あらかじめ表示させたい文字列を背景描画して表示しています.
ここでは,いちいち画像を準備したくないので,VisualBrushを使いTextBlockを描画するようにしました.さらに,TextBoxにフォーカスがあるか,有効なテキスト入力があるときは,背景が消えるよう,スタイルにMultiDataBindingを設定しました.
MultiBindingで動作するはずだったのですが,ConditionのProperty属性に"Text.Length"を設定すると,コンパイル時にプロパティが見つからないと怒られてしまったので,MultiDataBindingを使っています.

XAMLソースコードは以下のとおり.

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="100" Width="300">
    
    <Window.Resources>
        <!-- 背景描画につかうLabel -->
        <Label x:Key="_label">Label</Label>
        <!-- 背景描画につかうブラシ, 今回は共通利用いないので意味はないけど,複数の場所で使うならリソースにしておくといい, 省資源と(文字列などの)変更が1箇所ですむから -->
        <!-- 描画位置が画面左になるよう, AlighnmentX を設定. 描画時に引き伸ばされないように StrechはNoneに設定.-->
        <VisualBrush x:Key="_background" Stretch="None" AlignmentX="Left" >
            <VisualBrush.Visual>
                <TextBlock FontStyle="Italic" Foreground="Gray" FontSize="12" Text="input string..." />
            </VisualBrush.Visual>
        </VisualBrush>
    </Window.Resources>
    
    <DockPanel>
        <TextBox DockPanel.Dock="Top">
            <TextBox.Style>
                <Style TargetType="TextBox">
                    <Style.Triggers>
                        <!-- なぜだか Text.Length が見つからないとエラー.最初は動いていたはずなのだけど...
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsFocused" Value="False"/>
                                <Condition Property="Text.Length" Value="0"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background">
                                <Setter.Value>
                                    <VisualBrush Stretch="None" AlignmentX="Left">
                                        <VisualBrush.Visual>
                                            <TextBlock FontStyle="Italic" Foreground="Gray" FontSize="12" Text="input string..."/>
                                        </VisualBrush.Visual>
                                    </VisualBrush>
                                </Setter.Value>
                            </Setter>
                        </MultiTrigger>
                        -->
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text.Length}" Value="0"/>
                                <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsFocused}" Value="False"/>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Background" Value="{StaticResource _background}"/>
                        </MultiDataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBox.Style>
        </TextBox>
        <Button DockPanel.Dock="Top">OK</Button>
    </DockPanel>    
</Window>