XAML での空白の処理

XAML の言語規則では、空白の意味は XAML プロセッサの実装によって処理する必要があると定められています。 この記事では、これらの XAML 言語規則について説明します。 また、XAML プロセッサの Windows Presentation Foundation (WPF) 実装およびシリアル化用の XAML ライターで定義されている追加の空白処理についても説明します。

空白の定義

XML との一貫性、XAML の空白文字は、スペース、改行、タブです。これらは、それぞれ Unicode 値 0020、000A、0009 に対応します。

空白文字の正規化

既定では、XAML プロセッサで XAML ファイルを処理する際に、次に示す空白の正規化が行われます。

  1. 東アジア言語の文字間の改行文字が削除されます。 この用語の定義については、後の「東アジア言語の文字」を参照してください。

  2. すべての空白文字 (スペース、改行、タブ) は、スペースに変換されます。

  3. 連続した複数のスペースはすべて削除され、1 つのスペースに置換されます。

  4. 開始タグの直後にあるスペースは削除されます。

  5. 終了タグの直前にあるスペースは削除されます。

"既定" とは、 xml:space 属性の既定値で表される状態に対応します。

内部テキスト内の空白、および文字列プリミティブ

前の正規化規則は、XAML 要素内で検出された内部テキストに適用されます。 正規化の後、XAML プロセッサによって、次のようにして、すべての内部テキストが適切な型に変換されます。

  • プロパティの型がコレクションでなく、直接的に Object 型でもない場合、XAML プロセッサではその型の型コンバーターを使用して、その型への変換が試みられます。 その際、変換に失敗すると、コンパイル時のエラーが発生します。

  • プロパティの型がコレクションで、内部テキストが連続している (間に要素タグがない) 場合、その内部テキストは単一の Stringとして解析されます。 そのコレクション型が Stringを受け入れない場合にも、コンパイル時のエラーが発生します。

  • プロパティの型が Objectである場合、その内部テキストは単一の Stringとして解析されます。 その内部テキストの中に要素タグが含まれている場合には、コンパイル時のエラーが発生します。これは、 Object 型は単一のオブジェクト (String またはそれ以外) であることを意味しているためです。

  • プロパティの型がコレクションであり、内部テキストが連続していないことがあります。この場合、最初の部分文字列は String に変換されてコレクション項目として追加されます。中間にある要素はコレクション項目として追加され、この要素の後に続く部分文字列 (存在する場合) は 3 番目の String 項目としてコレクションに追加されます。

空白の保持

ソース XAML で空白を保持し、XAML プロセッサによる空白の正規化の影響を受けずに最終的に表示されるようにするには、いくつかの手法があります。

xml:space ="preserve" : 空白を保持する必要がある要素のレベルで、この属性を指定します。 この場合、要素を視覚的にわかりやすい入れ子として "美しく表示する" ためにコード編集アプリケーションによって追加されたスペースも含めて、すべての空白が保持されます。 ただし、これらのスペースが表示されるかどうかは、スペースを含んでいる要素のコンテンツ モデルによって決まります。 オブジェクト モデルの大多数では、属性の設定にかかわらず、空白に意味があるとは見なされないため、xml:space="preserve" をルート レベルで指定しないでください。 グローバルに xml:space を設定すると、一部の実装で XAML 処理 (特にシリアル化) のパフォーマンスに影響することがあります。 この属性は、文字列内の空白を表示する必要のある要素のレベル、または空白が意味を持つコレクションである要素のレベルでのみ設定することをお勧めします。

エンティティおよび改行しないスペース: XAML では、テキスト オブジェクト モデル内に任意の Unicode エンティティを配置できます。 改行しないスペース (UTF-8 エンコードでは  ) などの、専用のエンティティを使用できます。 また、改行しないスペース文字をサポートするリッチ テキスト コントロールを使用することもできます。 インデントなどのレイアウト特性をシミュレートするためにエンティティを使用する場合には、エンティティの実行時出力が、一般的なレイアウト システムにおけるインデントの生成機能を使用した場合よりも多くの要因 (パネルや余白の適切な使用など) に基づいて変化するため、注意が必要です。 たとえば、エンティティはフォントにマッピングされ、ユーザーのフォント選択に応じてサイズが変わる可能性があります。

東アジア言語の文字

"東アジア言語の文字" は、Unicode 文字範囲 U+20000 から U+2FFFD と U+30000 から U+3FFFD のセットとして定義されます。 このサブセットは、「CJK 表意文字」と呼ばれることもあります。 詳細については、「https://www.unicode.org」を参照してください。

空白とテキスト コンテンツ モデル

実際には、空白の保持は、すべてのコンテンツ モデルのサブセットに関してのみ問題になります。 このサブセットに含まれるのは、ある種のシングルトン String 型、専用の String コレクション、または StringIList コレクションでの ICollection<T> と他の型の組み合わせをとることのできるコンテンツ モデルです。

WPF での空白とテキスト コンテンツ モデル

一例として、このセクションの残りの部分では、WPF によって定義されている特定の型について説明します。 この記事で説明する空白処理機能は、.NET XAML サービスと WPF の両方に関連しています。 これらの動作を実際に見るには、何かの WPF XAML マークアップを使用し、オブジェクト グラフでその結果を確認し、再度マークアップにシリアル化してください。

文字列を受け取ることのできるコンテンツ モデルの場合でも、そのコンテンツ モデル内での既定の動作では、残っているすべての空白は、意味のある空白としては扱われません。 たとえば、ListBoxIList を受け取りますが、空白 (各 ListBoxItem の間の改行など) は保持も表示もされません。 改行文字を ListBoxItem 項目の文字列間の区切り記号として使用しても、まったく機能しません。改行文字で区切られた文字列は、1 つの文字列および 1 つの項目として扱われます。

空白を意味のあるものとして扱うコレクションは、通常、フロー ドキュメント モデルの一部分です。 空白を保持する動作をサポートする主なコレクションには、InlineCollection があります。 このコレクション クラスは WhitespaceSignificantCollectionAttribute を使用して宣言します。この属性が検出されると、XAML プロセッサにより、コレクション内の空白は意味のあるものとして扱われます。 WhitespaceSignificantCollectionAttribute で示されたコレクション内の xml:space="preserve" と空白の組み合わせの場合、すべての空白は保持および表示されます。 xml:space="default"WhitespaceSignificantCollectionAttribute 内の空白の組み合わせの場合、前に説明した空白の初期正規化が行われます。その結果、特定の位置に 1 つのスペースが残り、それらのスペースが保持および表示されます。 どちらの動作が望ましいかは、開発者の意図によって異なります。そのため、 xml:space は、必要な動作が有効となるように、選択的に使用する必要があります。

また、フロー ドキュメント モデルで改行を意味する特定のインライン要素では、空白が意味を持つコレクションでも、余分なスペースを挿入しないように注意する必要があります。 たとえば、LineBreak 要素の用途は HTML の <BR/> タグと同じですが、マークアップの読みやすさのために、通常、LineBreak は改行を入れて後続のテキストから区切られます。 その改行は、正規化されて後続の行の先頭のスペースになってはなりません。 この動作を有効にするために、LineBreak 要素のクラス定義により、TrimSurroundingWhitespaceAttribute が適用されます。その結果、XAML プロセッサにより、LineBreak を囲む空白は常にトリミングされるという意味に解釈されるようになります。

関連項目