WPFのGrid上にコントロールを重ねて表示することでウォーターマーク(プレースフォルダ)機能を実装する

C# コンピュータ
C#

Gridにコントロールを複数配置するとコントロールが重なって配置されます。

Grid上にTextBlockを配置

<Window x:Class="GridOnTextBox01.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:GridOnTextBox01"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBlock Width="300" FontSize="24" Text="TextBlockの文字列" Foreground="Blue" />
    </Grid>
</Window>

Grid上にTextBox、TextBlockを順番に配置

<Window x:Class="GridOnTextBox01.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:GridOnTextBox01"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBox Width="300" FontSize="24" Text="TextBoxの文字列" Foreground="Green" />
        <TextBlock Width="300" FontSize="24" Text="TextBlockの文字列" Foreground="Blue" />
    </Grid>
</Window>


緑色の文字列はテキストボックスだか書き換えることが出来ない。

TextBoxとTextBlockが同じ位置に配置されたため文字が重なっています。
ただ、この状態だと機能的に問題がありまして、TextBox、TextBlockの順に定義したことにより、TextBoxが奥でTextBlockが手前に配置されます。
手前のコントロールのTextBlockのイベントが拾われるらしく、結果TextBoxに対して入力が出来ません。

TextBlockのイベントを無視する

<Window x:Class="GridOnTextBox01.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:GridOnTextBox01"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBox Width="300" FontSize="24" Text="TextBoxの文字列" Foreground="Green" />
        <TextBlock IsHitTestVisible="False" Width="300" FontSize="24" Text="TextBlockの文字列" Foreground="Blue" />
    </Grid>
</Window>

TextBlockにIsHitTestVisibleプロパティをFalseでセットするとTextBlockで発生するイベントが無視されるようになり、結果TextBoxが入力できるようになります。

緑色のテキストボックス文字列が書き換えることが出来るようになりました。

ウォーターマーク(プレースフォルダ)

最近のTextBoxのUIは入力を促すような文字列が表示され、入力が開始するとその文字列は消える機能があります。
ウォーターマークとかプレースフォルダとか呼ばれているようです。

前段のコントロールを重ね合わせることでウォーターマーク(プレースフォルダ)機能を実装してみます。

<Window x:Class="GridOnTextBox01.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:GridOnTextBox01"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBox x:Name="SearchWord" Width="300" FontSize="24" Text="" Foreground="Black" />
        <TextBlock IsHitTestVisible="False" Width="300" FontSize="24" Text="文字を入力" Foreground="DarkGray">
            <TextBlock.Style>
                <Style TargetType="{x:Type TextBlock}">
                    <Setter Property="Visibility" Value="Collapsed"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Text, ElementName=SearchWord}" Value="">
                            <Setter Property="Visibility" Value="Visible"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>

    </Grid>
</Window>

初期状態ではTextBlockのText「文字を入力」が表示される。

文字を入力すると「文字を入力」がきえて入力文字列が表示される。

入力が開始すると文字列消すトリックは、
まず、TextBlockをSetterで非表示(Collapsed)に設定しこちらがデフォルトになります。
しかし、次の行のDataTriggerでTextBox(名前SearchWord)のTextプロパティが未入力(“”)の場合、SetterでTextBlockを表示(Visible)にしています。
こうすることで、TextBoxが未入力(“”)の状態の場合、TextBlockが表示状態になり「文字を入力」の文字が見えるが、TextBoxに入力が開始されるとTextBlockが非表示になり、TextBoxの入力した文字列が見える仕掛けになっています。

コメント