.NET MAUIのStackLayout問題を解決:AndExpandをGrid(*)に置き換えるレイアウト設計

.NET MAUIで画面を組むと、縦横に並べるだけならVerticalStackLayout/HorizontalStackLayoutが快適です。ところが少し複雑になると「FillAndExpandが欲しい…」となり、StackLayoutに戻りたくなることも。ここではAndExpandの正体を整理し、Grid(*)で安全に置き換える実務パターンをまとめます。

目次

結論:単純な縦/横並びはStack系、領域配分(伸びる)はGridが最適解

最初に結論を固定します。迷ったらこのルールに戻ると、画面設計がブレにくくなります。

やりたいこと推奨レイアウト理由(実務目線)
単純な縦積み(フォーム、設定画面、説明文+ボタンなど)VerticalStackLayout意図が明確で読みやすい。StackLayoutより最適化されている前提で使える。
単純な横並び(アイコン+テキスト、左右ボタンなど)HorizontalStackLayout同上。Orientationの指定が不要で、構造が単純。
「余った領域を誰が取るか」を明確にしたい(スクロール領域、一覧、空白スペーサーなど)Grid(* / Auto)AndExpandでやりたかった領域配分を、行/列で明示できる。保守が楽。
折り返し・可変配置(タグのように並べる、レスポンシブ風に回り込み)FlexLayoutStackやGridで無理にやるより素直。だが乱用すると意図が読みにくいので限定的に。

つまり、「StackLayoutを使い続けていいのか」問題は、AndExpandに依存しない設計へ寄せると自然に解消します。AndExpandが必要になった瞬間に「Gridの出番」と判断するのが一番安全です。

AndExpand(FillAndExpandなど)の正体:子ではなく“親(StackLayout)”の都合で効く仕組み

まず誤解されやすい点を整理します。FillAndExpand / CenterAndExpand などは、見た目としては「要素が伸びる魔法」ですが、実態はLayoutOptionsの“Expandフラグ”で、これを解釈するかどうかは親レイアウト次第です。

AndExpandが意味を持つのは、基本的にStackLayoutだけ

AndExpandは、Xamarin.Forms時代からの互換的な挙動として、主にStackLayoutが「余った領域をExpand指定の子に配る」ために存在します。逆に言うと、StackLayout以外(GridやFlexLayoutなど)では、Expandの解釈がされず“効いたように見えない/実は無意味”になりがちです。

ここで重要なのは、AndExpandは「子が勝手に伸びる」のではなく、親が子に領域を配分するための目印だという点です。親がその目印を見ないなら、何も起きません。

積み方向と直交するAndExpandは、StackLayout内でも無意味になりやすい

StackLayoutは「積み方向(縦 or 横)」に沿って子要素を並べます。AndExpandで“余りを配る”のも基本は積み方向です。

親がStackLayoutで…意味が出やすい指定整理対象になりやすい指定コメント
縦積み(Vertical)子のVerticalOptions=”FillAndExpand” など子のHorizontalOptions=”CenterAndExpand” など横方向はFill/Center/Endなどの“配置”は効くが、Expandは余り配分の対象外になりやすい。
横積み(Horizontal)子のHorizontalOptions=”FillAndExpand” など子のVerticalOptions=”CenterAndExpand” など縦方向のExpandは読み手に誤解を与えやすい(「伸びるはず」と期待する)ので削除候補。

実務的には、「AndExpandを付けたのに効いてない」のほとんどがこのパターンです。レイアウトの読みやすさも落ちるので、まずはここを掃除すると画面の挙動が安定します。

なぜVerticalStackLayout/HorizontalStackLayoutを使うのか

.NET MAUIでは、StackLayoutの代わりにVerticalStackLayout / HorizontalStackLayoutが用意されています。目的はシンプルで、よく使う縦積み・横積みのケースを分けることで、意図が明確になり、内部的にも最適化しやすくなるからです。

ただし、ここが今回のテーマの核心ですが、AndExpandに依存した「余りを配る」設計を続けると、どうしてもStackLayoutに戻りたくなります。そこで、次の章でAndExpandをGridに翻訳する考え方を固定します。

AndExpandをGrid(*)へ置き換える発想:Autoと*で「伸びる領域」を宣言する

AndExpandがやりたかったことは、乱暴に言えば「余った領域を取る(伸びる)」です。これをGridでは、行(RowDefinitions)や列(ColumnDefinitions)にスターサイズ(*)を使うことで、はるかに明示的に表現できます。

GridのAuto / * を実務でどう使い分けるか

指定意味向いている要素よくある例
Auto内容に必要な分だけ確保ヘッダー、ラベル、固定ボタン列タイトル、検索バー、フッターボタン
*(スター)余った領域を取る(伸びる)スクロール領域、一覧、可変の本文CollectionView、ScrollView、エディタ領域
2* / 3*比率で配分左右ペイン、上段/下段の比率左メニュー:右コンテンツ=1*:3*

AndExpandは「Expand指定の子が複数あると均等配分」になりやすく、微調整が面倒になりがちです。Gridなら2*や3*で比率を指定できるので、画面の要件が増えても破綻しにくいのが大きな利点です。

置き換えレシピ:FillAndExpandが出てきたらGridに翻訳する

ここからは「実務でそのまま貼って使える」置き換えパターンです。AndExpandを見かけたら、まずは次のテンプレートを当てはめてください。

パターン:ヘッダー固定+本文が伸びる+フッター固定

最も出現率が高い構成です。StackLayout+ScrollView(または一覧)がFillAndExpandになっている場合は、ほぼこの置き換えで解決します。

Before(StackLayout+FillAndExpand)

<StackLayout Padding="16">
  <Label Text="設定" FontSize="24" />








After(Grid+Auto,*,Auto)

<Grid Padding="16"
      RowDefinitions="Auto,*,Auto">










この形にしておくと、後から「フッターを2段にする」「ヘッダーに検索欄を足す」「本文をCollectionViewにする」などの変更が入っても、行定義を触るだけで対応できます。

パターン:左右(または上下)で片方だけ伸びる

横方向のFillAndExpandを使って「右側だけ伸びる入力欄」を作っている場合は、GridのAuto,*が定番です。

Before(Horizontal StackLayout+FillAndExpand)

&lt;StackLayout Orientation="Horizontal" Spacing="12"&gt;
  &lt;Label Text="名前" VerticalOptions="Center" /&gt;
  &lt;Entry HorizontalOptions="FillAndExpand" /&gt;
&lt;/StackLayout&gt;

After(Grid+Auto,*)

&lt;Grid ColumnDefinitions="Auto,*" ColumnSpacing="12"&gt;
  &lt;Label Text="名前" VerticalOptions="Center" /&gt;
  &lt;Entry Grid.Column="1" /&gt;
&lt;/Grid&gt;

この置き換えは見た目の再現度が高く、かつコードレビューで「右が伸びる構造」が一目で分かります。

パターン:間に“余白スペーサー”を入れて下に押し下げたい

「上に説明、下にボタン。間は空けたい」系の画面では、AndExpandを“スペーサー用のBoxView”に付けていることがあります。Gridならもっと自然に書けます。

Before(スペーサーがFillAndExpand)

<StackLayout Padding="16">
  <Label Text="説明文" />



After(Gridの*行がスペーサーになる)

<Grid Padding="16" RowDefinitions="Auto,*,Auto">
  <Label Text="説明文" />



“何も置かない行”を作れるのがGridの強みです。ダミー要素が消えるので、アクセシビリティやテスト面でも有利です。

「AndExpandが効かない」典型パターンと、削除してよいサイン

既存コードの整理をするときに、まず当たりを付けやすいポイントをまとめます。AndExpandを闇雲に消すのではなく、“親が何か”と“積み方向が何か”だけ確認すれば、削除可否の判断はかなり簡単になります。

親がGrid/FlexLayout/AbsoluteLayout/ScrollViewなのにAndExpandが付いている

この場合、AndExpandは効いていないか、意図通りではないことがほとんどです。

  • まずはExpandを外して見た目が変わるかを確認(変わらないなら削除してOK)。
  • 「伸ばしたい」意図があるなら、親をGridにして*行/*列で表現する。

縦積みなのにHorizontalOptions=”…AndExpand” が混ざっている

縦に積むStackLayout(またはVerticalStackLayout)で、横方向のAndExpandが混ざっているのは、保守上かなり危険です。次のように置き換えると意図が明確になります。

Before(誤解されやすい)

&lt;StackLayout&gt;
  &lt;Label Text="タイトル"
         HorizontalOptions="CenterAndExpand" /&gt;
&lt;/StackLayout&gt;

After(意図通りならこれで十分)

&lt;VerticalStackLayout&gt;
  &lt;Label Text="タイトル"
         HorizontalOptions="Center" /&gt;
&lt;/VerticalStackLayout&gt;

“Centerなのか、Fillなのか、余白も含めて伸ばしたいのか”を混ぜないことが、レイアウト事故を防ぐコツです。

Gridで置き換えるときにハマりやすい注意点

AndExpand → Grid(*)の置き換えは強力ですが、いくつか落とし穴もあります。ここを押さえると、移行が一気に楽になります。

ScrollViewの“中”では*(スター)が期待通りに動かないことがある

ScrollViewは「中身をスクロールできるように」高さ(または幅)の制約が緩くなりやすいレイアウトです。結果として、ScrollViewの中にGridを置いたときに*行が“余り”を認識できず、伸びないことがあります。

  • 「画面全体で伸びる領域」を作りたい場合は、Gridの*行にScrollViewを置く(ScrollViewを外側へ)
  • 「ScrollViewの中で比率を取りたい」は、発想を変えてAuto中心にするか、UI要件自体を見直す(スクロール領域内での“余り”は定義しにくい)

この違いを理解しておくと、「Gridにしたのに伸びない」問題を早い段階で切り分けできます。

Gridを“全部”に使うのではなく、骨格だけGridにする

Gridは万能ですが、細部までGridで組むと、行/列が増えて逆に読みづらくなります。おすすめは「画面の骨格だけGrid」+「セル内はVerticalStackLayout/HorizontalStackLayout」です。

例:骨格をGrid、内容はStack系で読みやすく

<Grid RowDefinitions="Auto,*,Auto" Padding="16">
















  <Grid ColumnDefinitions="Auto,*" ColumnSpacing="12">
    <Label Text="メモ" VerticalOptions="Start" />
    <Editor Grid.Column="1" AutoSize="TextChanges" />
  </Grid>
</VerticalStackLayout>





こうすると、構造はGridで“領域配分”を担保しつつ、内容はStack系でスッキリ書けます。

「StackLayoutは将来なくなる?」不安への現実的な向き合い方

「StackLayoutが廃止されたら困るから、今のうちに全部置き換えた方がいいのか?」という不安は自然です。ただ実務の判断は、白黒ではなく“影響範囲を小さくする”方向が現実的です。

  • 新規実装は、基本をVerticalStackLayout/HorizontalStackLayout+Gridに寄せる
  • 既存画面は、AndExpandが絡む箇所から優先してGridへ(挙動のバグ混入を減らしやすい)
  • 移行の目的は「廃止対策」よりも、レイアウトの意図を明文化して保守性を上げることに置く

StackLayout自体は互換性の観点から残り続ける可能性もありますが、将来どうなるかを100%予測するより、AndExpandへの依存を減らしておく方が、結果的に移行コストも障害も減ります。

移行の進め方:AndExpand駆動から“宣言的な領域配分”へ

大きな画面を一気に書き換えると事故りやすいので、順番を決めて進めると安全です。

手順のおすすめ

  • Step 1:画面の最外枠をGridにする(Auto,*,Autoなど)
  • Step 2:FillAndExpandが付いていた要素を、*行/*列へ移す
  • Step 3:StackLayoutをVerticalStackLayout/HorizontalStackLayoutへ置換(AndExpandが残っていない箇所から)
  • Step 4:“効いていないAndExpand”を削除し、見た目が変わらないことを確認
  • Step 5:余白(Margin/Spacing)と整列(HorizontalOptions/VerticalOptions)を最終調整

検証を楽にするコツ

  • 一時的に各ブロックへ背景色(またはBorder)を付けて、領域の境界を可視化する
  • 端末サイズを変えて(スマホ縦/横、タブレット)レイアウトが破綻しないか確認する
  • 一覧が絡む場合は、ScrollViewではなくCollectionViewの利用も検討する(大量要素での体感が変わる)

よくある質問(現場で詰まりやすいポイント)

FillとFillAndExpandの違いは何ですか?

Fillは「与えられた領域の中で、要素を伸ばして埋める(ストレッチする)」ニュアンスです。一方でExpandは「余った領域を自分に割り当ててもらう」ニュアンスで、親(主にStackLayout)の配分ロジックに依存します。混ぜると理解が難しくなるので、領域配分はGrid、要素の伸縮はFill、という風に役割を分けると整理しやすいです。

Gridにしたら、以前よりコードが増えませんか?

最初はRowDefinitions/ColumnDefinitionsが増えるため増えたように見えます。ただ、画面要件が増えたときにAndExpandの追加や順番調整で泥沼化するリスクが減るため、トータルでは保守が楽になるケースが多いです。特に「固定ヘッダー/固定フッター/中央が伸びる」構造は、Gridで型を作ってしまうと圧倒的に安定します。

VerticalStackLayoutだけでどうにかなりませんか?

単純なフォームなら十分いけます。ただ「中央だけ伸びる」「左右比率で配分する」「下に固定ボタンを置く」などが出た時点で、Stack系だけで頑張るとAndExpand依存やダミー要素が増えやすくなります。そこがGridへ切り替える合図です。

まとめ:迷いを消すためのチェックリスト

  • 単純な縦/横並びはVerticalStackLayout/HorizontalStackLayout
  • 「余った領域を取る」が必要ならGridの*(スターサイズ)
  • AndExpandは親がStackLayout以外なら基本的に期待しない
  • StackLayout内でも、積み方向と直交するAndExpandは整理対象
  • 画面の骨格をGridにして、セル内はStack系にすると読みやすさと拡張性が両立

AndExpandは便利に見えますが、設計の主導権が“子”ではなく“親の配分ロジック”に寄るため、画面が育つほどコントロールしづらくなります。Grid(Autoと*)で領域配分を宣言し、Stack系は「並べる」役に徹させる。これが.NET MAUIでレイアウトを安定させる一番実務的な落とし所です。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次