imani-cの日記

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

WPF - TextBlock

TextBlockは、高々数行までの文字列を表示するためのコントロールです。MSのドキュメントによると、1行の表示には最高、数行までなら高パフォーマンスで表示できるようです。

表示するテキストを指定する

直接テキストを指定することができます。

<!-- 文字列指定方法1 : 属性としてテキストを指定する-->
<TextBlock Text="String to show"/>

<!-- 文字列指定方法2 : コンテンツとしてテキストを指定する -->
<TextBlock>
    String to Show
</TextBlock>

どちらでも同じ表示になります。

f:id:imani-c:20220418083017p:plain
直接テキストを指定

「その2」は単純にテキストを指定したのとは異なりいろいろな融通の利く方法なのですが、それについては別の記事で紹介します。

文字列の途中に改行を入れるには、「 」か「 」を改行したいところに置きます。

<!-- 文字列中に改行を置く-->
<TextBlock Text="String&#x0a;to show"/>

f:id:imani-c:20220418083104p:plain
テキスト中に改行

Bindingによる表示

TextBlockのText属性をビューモデルなどのプロパティにバインドすることができます。

<!-- 属性としてBindingする-->
<TextBlock Text="{Binding StringProperty}"/>

<!-- 属性を使わない書き方-->
<TextBlock>
    <TextBlock.Text>
        <Binding Path="StringProperty"/>
    </TextBlock.Text>
</TextBlock>

他のコントロールにバインドすることもできます。下記の例では、上側のTextBoxで編集した文字列が下側のTextBlockにリアルタイムに表示されます。

<!-- ほかのコントロールのTextにバインドする-->
<TextBox Name="anotherTextBlock" Text="This is another TextBlock."/>
<TextBlock Text="{Binding ElementName=anotherTextBlock, Path=Text}"/>

MultiBindingによる表示

MultiBindingを使うと、一つのTextBlockに複数のプロパティの内容を表示できます。

<TextBlock>
    <TextBlock.Text>
        <MultiBinding StringFormat="First={0}, Second={1}>
          <Binding Path="FirstStringProperty"/>
          <Binding Path="SecondStringProperty"/>
      </MultiBinding>
    </TextBlock.Text>
</TextBlock>

この例では、FirstStringPropertyとSecondStringPropertyは、ビューモデルなどにあるString型のプロパティです。

MultiBindingでは、書式を指定するStringFormatが必要です。MultiBindingで指定されたものだけが有効で、それぞれのBindingで指定したものは無視されます。

書式指定の方法については、別の記事で紹介します。

見た目を変更する

フォントを指定する

フォントについては、以下の属性を変更できます。見た目に変化が感じられない属性や値を省略しています。

属性 指定内容 指定できる値(先頭がデフォルト)
FontFamily フォントの種類 フォント名
FontSize 文字サイズ バイス非依存のピクセル単位
FontStyle イタリックなどを指定 Normal, Italic
FontWeight 文字の太さを指定 Normal, Bold, Light

文字色と背景色を変更する。

シンプルに色を指定する例を掲げます。

<TextBlock Text="Colored string" Foreground="Red" Background="Silver" />

f:id:imani-c:20220418083138p:plain
色付きのTextBlock
ForegroundとBackgroundには、任意のSystem.Windows.Media.Brushから派生したブラシを設定できます。以下は、グラデーション付きのブラシを使った例です。

<TextBlock Text="Gradation background">
    <TextBlock.Background>
        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0" Color="White"/>
            <GradientStop Offset="1" Color="Silver"/>
        </LinearGradientBrush>
    </TextBlock.Background>
</TextBlock>

f:id:imani-c:20220418083202p:plain
グラデーション付きの背景

テキスト表示位置

TextBlockの領域内のどこに文字列を表示するのかを指定できます。

<StackPanel Width="200">
    <TextBlock Text="Left aligned" Background="LightGray"
               TextAlignment="Left" />
    <TextBlock Text="Center aligned" Background="LightCyan"
               TextAlignment="Center"/>
    <TextBlock Text="Right aligned" Background="SkyBlue"
               TextAlignment="Right"/>
</StackPanel>

f:id:imani-c:20220418083224p:plain
コントロール中のテキスト配置

縦方向の表示位置

TextBlockは、縦方向の表示位置を制御できません。しかし、与えられた領域の中心に文字列を表示したいことはよくあります。そのような時には、Borderなどの助けを借りることになります。

<Border>
    <TextBlock Text="Vertical center&#x0a;This is second line."
               TextAlignment="Center"
               VerticalAlignment="Center"/>
</Border>

f:id:imani-c:20220418083239p:plain
縦方向のセンタリング

この方法は、与えられた領域全体を占めるのはBorder要素であり、TextBlockは、その中心部分に配置されます。TextBlockはこの領域より小さい可能性がありますので、この領域の背景色を指定したいのであれば、Border側に指定する必要があります。

上記では水平方向の中心に表示させるために「TextAlignment="Center"」を指定しています。この部分を「HorizontalAlignment="Center"」に変更してもほぼ同じ効果を得られます。ただし、2行目以降がある場合には領域内でセンタリングされたようには見えなくなります。上記の例でHorizontalAlignmentを使うと、領域の中心付近で左寄せして表示されます。

はみ出す文字列の扱い

幅の上限が決まっているTextBlockでは、長い文字列を表示しようとしてもTextBlockの領域をはみ出してしまうことがあります。そのような時にどのように表示するかを指定できます。

属性 指定内容 指定できる値(先頭がデフォルト)
TextTrimming 文字列の省略方法 None, CharacterEllipsis, WordEllipsis
TextWrapping テキスト折り返し方法 NoWrap, Wrap, WrapWithOverflow
IsHphenationEnabled ハイフンによる単語分割の可否 False,True

TextWrappingとTextTrimminの例を掲げます。

<TextBlock Text="Long string to explain text wrapping and text trimming."
            Width="100" Height="40" Background="LightGray"
           TextWrapping="NoWrap" TextTrimming="CharacterEllipsis"/>
<TextBlock Text="Long string to explain text wrapping and text trimming."
            Width="100" Height="40" Background="Silver"
           TextWrapping="Wrap" TextTrimming="WordEllipsis"/>

f:id:imani-c:20220418083258p:plain
TextWrapingとTextTrimming
IsHphenationEnabledについては、適切な例を作れませんでした。

行の高さ

行の高さは、以下の二つの属性により制御できます。

属性 指定内容 指定できる値(先頭がデフォルト)
LineHeight 行の高さ 数値(デフォルトはフォントサイズにより決まる値)
LineStackingStrategy 行高の適用方法 MaxHeight, BlockLineHeight

LineHeightには、行の高さをデバイスに依存しないピクセル数で指定します。

  • 指定しなければ、行が正しく表示される高さになります。
  • LineHeightにそれより大きな値を指定すると、指定通りの行の高さになります。
  • LineHeightにそれより小さな値を指定した場合、LineStackingStrategyの指定によりLineHeightの適用方法が変わります。
    • LineStackingStrategyがデフォルトのMaxHeightなら、正しく表示される行高になります。行が重なって表示されることはありません。
    • LineStackingStrategyがBlockLineHeightなら、LineHeight通りの行高になります。複数の行が重なって表示されることになります。また行がTextBlockコントロールの範囲を超えて表示されます。 下記コードには、LineStackingStrategyだけが違う2個のTextBlockが含まれています。
            <TextBlock Text="Long string to explain LineHeight."
                       Width="100" TextWrapping="Wrap" Background="Silver"
                       LineStackingStrategy="BlockLineHeight" LineHeight="5"/>
            <TextBlock Text="Long string to explain LineHeight."
                       Width="100" TextWrapping="Wrap" Background="LightGray"
                       LineStackingStrategy="MaxHeight" LineHeight="5"/>

f:id:imani-c:20220418083321p:plain
LineStackingStrategyとLineHeight