imani-cの日記

WPFスタイルとテンプレートの本をAmazonで出しました。ちょっととっつきにくいこれらについて知りたいお方は、覗いてみてください。「WPF スタイル」で検索すると、トップに出ます。gRPCの本もあります。「gRPC入門」で検索するとすぐ見つかります。

WPF - TextBlock.TextDecorations

TextBlockやTextBlock.Inlinesに置かれた文字列には、いくつかの装飾を付けることができます。

  • Overline : 上線
  • StrikeThrough : 取り消し線
  • Underline : 下線
  • Baseline : ベースライン

これらすべてを表示した例を掲げます。

<TextBlock Text="String to show" FontSize="40">
    <TextBlock.TextDecorations>
        <TextDecorationCollection>
            <TextDecoration Location="Strikethrough" />
            <TextDecoration Location="OverLine"/>
            <TextDecoration Location="Underline" />
            <TextDecoration Location="Baseline" />
        </TextDecorationCollection>
    </TextBlock.TextDecorations>
</TextBlock>

f:id:imani-c:20220418084606p:plain
すべての装飾を付けた文字列

TextDecoration要素のLocationを省略すると、Underlineになります。

装飾に色を付ける

デフォルトでは装飾に親のTextBlockの文字列と同じ色が付きますが、別の色を指定することもできます。

<TextBlock Text="String to show" FontSize="40">
    <TextBlock.TextDecorations>
        <TextDecorationCollection>
            <TextDecoration Location="Strikethrough">
                <TextDecoration.Pen>
                    <Pen Thickness="2" Brush="Red"/>
                </TextDecoration.Pen>
            </TextDecoration>
        </TextDecorationCollection>
    </TextBlock.TextDecorations>
</TextBlock>

f:id:imani-c:20220418084302p:plain
赤い取り消し線
上のコードは、少々煩雑です。以下のように、ペンの設定をリソースにする方が分かりやすいでしょう。また、リソースにしておけば、あちらこちらで使いまわしが効きます。

<TextBlock Text="String to show" FontSize="40">
    <TextBlock.Resources>
        <Pen x:Key="RedPen" Thickness="2" Brush="Red"/>
        <Pen x:Key="BluePen" Thickness="2" Brush="Blue"/>
    </TextBlock.Resources>
    <TextBlock.TextDecorations>
        <TextDecorationCollection>
            <TextDecoration Location="Strikethrough" Pen="{StaticResource RedPen}"/>
            <TextDecoration Location="Underline" Pen="{StaticResource BluePen}"/>
        </TextDecorationCollection>
    </TextBlock.TextDecorations>
</TextBlock>

f:id:imani-c:20220418084322p:plain
リソースを使った色付き装飾

スタイルを使って装飾を制御する

いかにもありそうな文字装飾の応用として、特定の条件を満たした文字列にア装飾などを付けるというものが考えられます。 以下のコードは、チェックボックスの状態により取り消し線の表示を制御する例です。上部のチェックボックスにチェックを付けると、取り消し線が表示されます。

<StackPanel Margin="20" HorizontalAlignment="Left"  Background="LightGray">
    <CheckBox Name="cbStrikeOut" Content="Check to strikeout"/>
    <TextBlock FontSize="40">
        <!-- 取り消し線のスタイル定義。実応用では共通リソースとして定義すべき。 -->
        <TextBlock.Resources>
            <!-- 取り消し専用のペン -->
            <Pen x:Key="RedPen" Thickness="2" Brush="Red"/>
            <!-- 取り消し線を表示するスタイル -->
            <Style x:Key="StrikeoutIfFalse" TargetType="{x:Type Run}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=cbStrikeOut, Path=IsChecked}" Value="True">
                        <Setter Property="TextDecorations">
                            <Setter.Value>
                                <TextDecorationCollection>
                                    <TextDecoration Location="Strikethrough"
                                                    Pen="{StaticResource RedPen}"/>
                                </TextDecorationCollection>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Resources>
        <!-- 表示文字列 -->
        String to
        <Run Text="show" Style="{StaticResource StrikeoutIfFalse}"/>
    </TextBlock>
</StackPanel>

f:id:imani-c:20220418084442p:plain
スタイルによる文字装飾

この例では「show」だけに取り消し線が表示されますが、Run要素にスタイルを設定する例を書いてみたかっただけです。実応用では、TextBlock用のスタイルを作ってテキストボックス全体に取り消し線を表示する方が普通でしょう。 また、この例では画面上のチェックボックスの状態により表示を変更していますが、実応用ではビューモデルのプロパティにバインドするべきです。