WPF 標準コントロールデモアプリ › Label

Label Display

Label は、主に入力欄の見出しを表示し、アクセスキーでその入力欄へキーボードフォーカスを移せるコントロールです。

アクセスキーでフォーカスがどこへ移るか

Label は ContentControl を継承しています。Label 自身は、既定ではフォーカスを受け取りません。Focusable も IsTabStop も False で、Label の前の TextBox から Tab を押すと、Label の後の TextBox へ直接移りました。Label がするのはフォーカスの受け渡しで、Target は Label のアクセスキーを押したときにフォーカスを受け取る要素です。

_Name(Press Alt+N) と _Age(Press Alt+A) では、アクセスキー N と A を AccessKeyManager.ProcessKey で処理させると、フォーカスが Name と Age のテキストボックスへ移りました(実際のキー入力は測っていません)。Target のない _Plain のアクセスキーでは、フォーカスは動きませんでした。アクセスキーを付けた見出しには必ず Target を設定します。フォーカススコープが違っても問題はなく、ToolBar の中の TextBox を Target にした Label でも、フォーカスがその中へ移りました。ほかのコントロールも対象にでき、アクセスキーで、ComboBox ではそれ自体に、編集可能な ComboBox と DatePicker では中のテキストボックスにフォーカスが移りました。

Target はスクリーンリーダー向けの名前にならない

Label クラスのドキュメントには、Target を設定すると UI オートメーションがラベルの文字を対象の名前に使うと書かれていますが、.NET 10 ではそうなりませんでした。スクリーンリーダーも使う UI オートメーションのクライアント API で読むと、Name のテキストボックスの名前は空で、LabeledBy もありませんでした。これは未解決の報告 dotnet/wpf#9185 と一致します。

名前は別に付けます。入力欄の AutomationProperties.LabeledBy に Label を設定すると効き、Age のテキストボックスの名前は「Age(Press Alt+A)」になりました。

条件 計測値
基底クラス / Focusable、IsTabStop / Padding / 内容の配置 ContentControl / False, False / 5,5,5,5 / Left, Top
TextBox、Label、TextBox の順: 最初の TextBox から Tab で移る先 2 つ目の TextBox
デモの Target 付きの Label: アクセスキー N / A の後のフォーカス Name の TextBox / Age の TextBox
Name の TextBox を UI オートメーションのクライアントから読む: 名前 / LabeledBy (空) / なし
AutomationProperties.LabeledBy を手で指定した Age の TextBox: 名前 / LabeledBy Age(Press Alt+A) / Age(Press Alt+A)
Target の無い Label "_Plain": アクセスキー P の後のフォーカス Other(変わらない)
Target が ToolBar の中の TextBox(独自のフォーカススコープ): アクセスキー S の後のフォーカス ToolBar の中の TextBox
文字列の Content(1 行): 高さ 25.96
文字列の Content(改行あり): 高さ 41.92
アクセスキー、Target が ComboBox / 編集できる ComboBox / DatePicker: フォーカスの移る先 ComboBox / TextBox / DatePickerTextBox

既定値、アクセスキー、Target、UI オートメーション。.NET 10 / Windows 11 で計測。

見出しそのもの

文字列の内容はアクセスキーを認識して表示されます。アンダースコアの次の文字がアクセスキーになり、アンダースコア自体は表示されません。この点とアンダースコアの表示のしかたは、下にリンクした記事で扱っています。改行を含む文字列は 2 行で表示され、Label の高さは 1 行で 25.96、2 行で 41.92 でした。内容には任意の要素を置けるので、アイコンと文字を並べることもできます。

Padding の既定値は 4 辺とも 5 で、HorizontalContentAlignment と VerticalContentAlignment の既定値は Left と Top です。アクセスキーの要らない文字には TextBlock を使います。下にリンクした記事で、Label を大量に置いたときの負担を実測しています。

デモアプリで試す

デモアプリの Label のページ。左にコントロールの一覧、右に最初の節の Target

デモアプリの Label のページには、Target、内容と、Control のプロパティ(Padding、フォントの各プロパティ、Background、Foreground、枠、内容の配置)の欄があります。Target の欄には _Name(Press Alt+N) と _Age(Press Alt+A) の 2 組があり、内容の欄は見出しを複数行のテキストボックスにバインドしているので、文字に改行を入れると 2 行の Label になります。各欄の下の「Show Code」リンクで、その欄の XAML を表示できます。次の XAML は、Target の欄(LabelUsageControl.xaml)から、スタイルと周囲の GroupBox を省き、名前空間の宣言を加えたものです。

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="auto" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <Label x:Name="TargetNameLabel" Grid.Row="0" Grid.Column="0"
         Content="_Name(Press Alt+N)"
         Target="{Binding ElementName=TargetNameTextBox}" />
  <TextBox x:Name="TargetNameTextBox" Grid.Row="0" Grid.Column="1" />
  <Label x:Name="TargetAgeLabel" Grid.Row="1" Grid.Column="0"
         Content="_Age(Press Alt+A)"
         Target="{Binding ElementName=TargetAgeTextBox}" />
  <TextBox x:Name="TargetAgeTextBox" Grid.Row="1" Grid.Column="1" />
</Grid>

関連するコントロールと記事

ソースコードと計測の方法

このページの挙動の記述は、すべて .NET 10 / Windows 11 で実際に動かして確かめたものです。計測には、このサイトのスクリーンショット生成ツールの LabelDemoScene を使いました。アクセスキーは 指定したアクセスキーを、そのキーのキーダウンがアクセスキーの管理に渡された場合と同じように処理する AccessKeyManager.ProcessKey の呼び出しで(実際の Alt+キーの入力ではない)、Tab はキーボードから打ったときと同じく WPF の入力管理(InputManager)を通して送りました。UI オートメーションの名前は、スクリーンリーダーも使う UI オートメーションのクライアント API で、同じプロセスの中の、ウィンドウの UI スレッドとは別のスレッドから読みました。大きさは、計測したマシンでの値です。

GitHub で Label のソースコードを見る →