【XAML】1つのTextBlockで複数の書式（部分的にFontSize・FontWeightを異なるText）をいれる

# 背景

1つのTextBlockのなかに"xxx yyy zzz"という文字列を入れて、"yyy"だけFontSizeを大きくするとか、"zzz"だけBoldするという場合の方法を調べたので、まとめておきます。

# 複数のTextBlockを並べる場合

StackPanelを使ってTextBloclを複数並べて、実現してみます。

```xml
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="5">
    <StackPanel.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="VerticalAlignment" Value="Bottom"/>
        </Style>
    </StackPanel.Resources>
    <TextBlock>デフォルトのサイズ1</TextBlock>
    <TextBlock>デフォルトのサイズ2</TextBlock>
    <TextBlock FontSize="40">大きいサイズ</TextBlock>
    <TextBlock FontWeight="Bold">太字</TextBlock>
    <TextBlock FontSize="10">小さいサイズ</TextBlock>
</StackPanel>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2430330/1725a1ad-8f36-0569-7d5f-96ae7fed569d.png)
それっぽくできていますが、フォントサイズが異なっているので、余白が異なり(？)、下端がそろっていないように見えます。

# TextBlockのInlinesプロパティを使用する場合

TextBlockにはInlinesプロパティというものがあり、そこに複数の書式の文字列を入れることができます。
InlinesプロパティはInlieクラスのコレクション型のようで、Inlineクラスを継承したRunクラスを格納でき、このRunクラスにそれぞれフォーマットを指定していきます。

:::note warn
Inlinesプロパティは読み取り専用(getterのみ)で、DependencyPropertyでもないので、直接バインドすることはできないようです。
:::

## XAMLでの記述

XAMLで記述する場合はTextBlockのTextに`<Run>Text</Run>`を追加していけばよいです。
ハイパーリンクなどもこれで実現できるようです。

```xml
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" Margin="5">
    <Run>デフォルトのサイズ1</Run>
    <Run>デフォルトのサイズ2</Run>
    <Run FontSize="40">大きいサイズ</Run>
    <Run FontWeight="Bold">太字</Run>
    <Run FontSize="10">小さいサイズ</Run>
</TextBlock>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2430330/6d30bac2-7f9f-1165-128d-093c5b3abb0a.png)
しっかり下端がそろっているように見えます。
RunとRunの間にスペースが少し入るようです。(WinUI3)

## コードビハインドでの記述

Inlinesプロパティをコードビハインドから操作する方法です。
XAML上でTextBlockコントロールに名前を付けて、コードビハインドから操作します。

```xml
<TextBlock x:Name="myTexxtBlock" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="5"/>
```

```cs:コードビハインド
myTexxtBlock.Inlines.Clear();
var default1 = new Run() { Text = "デフォルトのサイズ2" };
var default2 = new Run() { Text = "デフォルトのサイズ2" };
var large = new Run() { Text = "大きいサイズ", FontSize = 40 };
var bold = new Run() { Text = "太字", FontWeight = FontWeights.Bold };
var small = new Run() { Text = "小さいサイズ", FontSize = 10 };
myTexxtBlock.Inlines.Add(default1);
myTexxtBlock.Inlines.Add(default2);
myTexxtBlock.Inlines.Add(large);
myTexxtBlock.Inlines.Add(bold);
myTexxtBlock.Inlines.Add(small);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2430330/91afe1ee-dfbd-2bea-acd4-7799fe952de3.png)
下端もそろっていますし、スペースも入りませんでした。

# まとめ

1つのTextBlockで複数の書式を入れるにはTextBlockのInlinesを使うのがよさそうです。
Inlinesを使用すると、最終的には1つのTextに結合されるようなので、ナレーター対応とかも考える必要がなさそうです。

今回作成したコードのリポジトリを置いておきます。WinUI3で作成しています。
Unpackagedをスタートアップにして実行すると動作すると思います。

https://github.com/nobushi95/TextBlockInlinesWinUI3

# 参考

https://learn.microsoft.com/ja-jp/uwp/api/windows.ui.xaml.controls.textblock.inlines?view=winrt-22621

https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.controls.textblock?view=windowsdesktop-7.0

https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.documents.run?view=winrt-22621

https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.documents.run?view=windowsdesktop-7.0