Avalonia UI - StackPanel

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

StackPanelは、Avalonia UIにおける最も基本的なレイアウトコントロールの1つである。

StackPanelは、子要素を垂直方向または水平方向に積み重ねることにより、一列に並べることができる。

また、Orientationプロパティを使用して、並べる方向を指定することができる。(デフォルトは垂直方向)

StackPanelは子要素のサイズを自動的に調整する。
例えば、垂直方向の場合、幅は親コンテナに合わせて調整されて、高さは子要素のサイズに応じて決定される。 (StackPanelの内部では、子要素のスタックに垂直なsizeプロパティが設定されていない場合、子要素は使用可能なスペースを埋めるために引き伸ばされる)

水平方向の場合はその逆となる。
(例えば、水平方向では、子コントロールの高さが設定されていない場合、子コントロールは引き伸ばされる)

以下の例では、垂直スタックパネルの作成方法を示している。
子要素は幅に合わせて引き伸ばされて、StackPanelの全体の高さは子要素の高さの合計に等しくなる。

 <StackPanel Width="200">
    <Rectangle Fill="Red"    Height="50"/>
    <Rectangle Fill="Blue"   Height="50"/>
    <Rectangle Fill="Green"  Height="100"/>
    <Rectangle Fill="Orange" Height="50"/>
 </StackPanel>


Spacingプロパティを使用することで、子要素間の間隔を指定できる。
これにより、要素間に均一な空白を設けることが可能となる。

また、HorizontalAlignmentプロパティあるいはVerticalAlignmentプロパティを使用して、パネル内での子要素の配置を制御できる。
これらは特に、パネルのサイズが子要素の合計サイズより大きい場合に効果を発揮する。

StackPanelは単純なレイアウトに適しているが、複雑なレイアウトを作成する場合は、GridやDockPanel等のより柔軟なレイアウトコントロールを使用する必要がある。

実務では、フォームの入力項目を縦に並べる場合やツールバーのボタンを横に並べる場合等、シンプルな1次元のレイアウトを実現する場合によく使用される。


基本的なプロパティ

プロパティ 説明
Orientation スタックの方向を設定する。
水平または垂直から選択する。
  • Vertical
    垂直方向に配置 (デフォルト値)
  • Horizontal
    水平方向に配置
Spacing 子要素間の間隔をピクセル単位で指定する。
例えば、10を指定すると各要素間に10ピクセルの空白が設定される。

デフォルトは0
Background パネルの背景色を指定する。
単色やグラデーション等、様々な背景スタイルを適用できる。
Margin StackPanel自体の外側の余白を指定する。
上下左右それぞれに異なる値を設定可能である。
Padding StackPanel内部の余白を指定する。
これにより、子要素との間にスペースを設けることができる。
HorizontalAlignment 親コンテナ内でのStackPanelの水平方向の配置位置を指定する。

以下に示す値から選択する。
  • Left
  • Center
  • Right
  • Stretch
VerticalAlignment 親コンテナ内でのStackPanelの垂直方向の配置位置を指定する。

以下に示す値から選択する。
  • Top
  • Center
  • Bottom
  • Stretch
IsVisible StackPanelの表示 / 非表示を制御する。
falseを指定する場合、StackPanelとその子要素が非表示になる。


StackPanelのプロパティの詳細を知りたい場合は、Avalonia UIの公式Webサイトを参照すること。


基本的なイベント

イベント 説明
PointerEntered
(マウスオーバー)
マウスポインタがStackPanel上に入った時に発生する。
例えば、パネルにマウスが重なった時に背景色を変更する、あるいは、ツールチップを表示する場合に使用する。
 <StackPanel PointerEntered="OnPointerEntered">
PointerExited
(マウスアウト)
マウスポインタがStackPanelから出た時に発生する。
例えば、PointerEnteredで変更した背景色を元に戻す、あるいは、表示したツールチップを非表示にする場合に使用する。
 <StackPanel PointerExited="OnPointerExited">
Loaded
(読み込み完了)
StackPanelがビジュアルツリーに読み込まれた時に発生する。
例えば、パネルの初期化処理や子要素の動的な追加等を行う場合に使用する。
 <StackPanel Loaded="OnLoaded">
Tapped
(タップ / クリック)
StackPanel上でタップまたはクリックされた時に発生する。
例えば、パネル全体をクリック可能な領域として使用する場合、あるいは、特定のアクションを実行する場合に使用する。
 <StackPanel Tapped="OnTapped">
SizeChanged
(サイズ変更)
StackPanelのサイズが変更された時に発生する。
例えば、パネルのサイズに応じて子要素のレイアウトを動的に調整する必要がある場合に使用する。
 <StackPanel SizeChanged="OnSizeChanged">


各イベントはコードビハインドを使用して、以下に示すように処理することができる。
以下の例では、マウスポインタがStackPanel上に入った時、StackPanelの背景色を変更している。

 private void OnPointerEntered(object sender, PointerEventArgs e)
 {
    var panel        = (StackPanel)sender;
    panel.Background = Brushes.LightBlue;
 }


StackPanelのイベントの詳細を知りたい場合は、Avalonia UIの公式Webサイトを参照すること。


基本的なメソッド

メソッド 説明
Children.Add
(要素追加)
StackPanelに子要素を動的に追加する。
例えば、実行時にユーザの操作に応じて、新しい要素を追加する場合などに使用する。
 var button = new Button { Content = "新しいボタン" };
 myStackPanel.Children.Add(button);
Children.Remove
(要素削除)
指定した子要素をStackPanelから削除する。
例えば、特定の要素を動的に削除する必要がある場合に使用する。
 if (myStackPanel.Children.Contains(targetElement))
 {
    myStackPanel.Children.Remove(targetElement);
 }
Children.Clear
(全要素削除)
StackPanel内の全ての子要素を削除する。
例えば、パネルの内容を完全にリセットする場合等に使用する。
 myStackPanel.Children.Clear();
FindControl<T>
(要素検索)
指定した型の子要素を検索する。
例えば、特定の子要素を名前で検索して操作する場合に使用する。
 var targetButton = myStackPanel.FindControl<Button>("buttonName");
 if (targetButton != null)
 {
    targetButton.Content = "更新されたテキスト";
 }
InvalidateVisual
(再描画要求)
StackPanelの視覚的な更新を要求する。
例えば、パネルの外観を手動で更新する必要がある場合に使用する。
 myStackPanel.InvalidateVisual();
BringIntoView
(表示位置調整)
StackPanelを視覚的に表示可能な位置までスクロールする。
例えば、スクロール可能なコンテナ内でパネルを確実に表示させる場合に使用する。
 await myStackPanel.BringIntoView();


※注意
上表のメソッドはコードビハインドやビューモデルから呼び出すことができる。
ただし、MVVMパターンを使用する場合は、可能な限りデータバインディングを使用することを推奨する。

例えば、Children.Addメソッドの代わりにItemsControlとコレクションを使用する等の方法がある。

なお、操作によっては、UIスレッド上での実行が必要な場合がある。

 await Dispatcher.UIThread.InvokeAsync(() =>
 {
    myStackPanel.Children.Add(newElement);
 });


StackPanelのメソッドの詳細を知りたい場合は、Avalonia UIの公式Webサイトを参照すること。


使用例

以下の例では、StackPanelは垂直方向に要素を配置して、フォーム全体を構成している。
ボタンおよびプルダウンの配置には、水平方向のStackPanelを使用している。

 <!-- MainWindow.axaml -->
 <Window xmlns="https://github.com/avaloniaui"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:Class="AvaloniaApplication.MainWindow"
         Title="StackPanel サンプル"
         Width="400"
         Height="500">
 
    <!-- メインのStackPanel - 垂直方向に要素を配置 -->
    <StackPanel Margin="20">
       <!-- ヘッダセクション -->
       <TextBlock Text="ユーザ情報入力"
                  FontSize="24"
                  FontWeight="Bold"
                  Margin="0,0,0,20"/>
 
       <!-- 入力フォームセクション -->
       <TextBlock Text="氏名:" Margin="0,0,0,5"/>
       <TextBox x:Name="NameTextBox"
                Margin="0,0,0,10"
                Watermark="氏名を入力してください"/>
 
       <!-- メールアドレス入力セクション -->
       <TextBlock Text="メールアドレス:" Margin="0,0,0,5"/>
       <TextBox x:Name="EmailTextBox"
                Margin="0,0,0,10"
                Watermark="メールアドレスを入力してください"/>
 
       <!-- 年齢入力セクション -->
       <TextBlock Text="年齢:" Margin="0,0,0,5"/>
       <NumericUpDown x:Name="AgeNumericUpDown"
                      Minimum="0"
                      Maximum="120"
                      Value="20"
                      Margin="0,0,0,20"/>
 
       <!-- 性別選択セクション - 水平方向のStackPanel -->
       <TextBlock Text="性別:" Margin="0,0,0,5"/>
       <StackPanel Orientation="Horizontal"
                   Spacing="10"
                   Margin="0,0,0,20">
          <RadioButton Content="Male" 
                       GroupName="Gender"
                       IsChecked="True"/>
          <RadioButton Content="Female" 
                       GroupName="Gender"/>
          <RadioButton Content="その他" 
                       GroupName="Gender"/>
       </StackPanel>
 
       <!-- 趣味選択セクション -->
       <TextBlock Text="趣味:" Margin="0,0,0,5"/>
       <StackPanel Margin="0,0,0,20">
          <CheckBox Content="読書" Margin="0,0,0,5"/>
          <CheckBox Content="スポーツ" Margin="0,0,0,5"/>
          <CheckBox Content="音楽" Margin="0,0,0,5"/>
          <CheckBox Content="旅行" Margin="0,0,0,5"/>
       </StackPanel>
 
       <!-- ボタンセクション - 水平方向のStackPanel -->
       <StackPanel Orientation="Horizontal"
                   HorizontalAlignment="Right"
                   Spacing="10">
          <Button Content="クリア"
                  Width="100"
                  x:Name="ClearButton"/>
          <Button Content="送信"
                  Width="100"
                  Classes="accent"
                  x:Name="SubmitButton"/>
       </StackPanel>
    </StackPanel>
 </Window>


 // MainWindow.axaml.csファイル
 
 using Avalonia.Controls;
 using Avalonia.Interactivity;
 using MsBox.Avalonia;
 
 namespace AvaloniaApplication
 {
    public partial class MainWindow : Window
    {
       public MainWindow()
       {
          InitializeComponent();
 
          // ボタンのクリックイベントハンドラを設定
          ClearButton.Click  += ClearButton_Click;
          SubmitButton.Click += SubmitButton_Click;
       }
 
       // クリアボタンを押下した時
       private void ClearButton_Click(object sender, RoutedEventArgs e)
       {
          // 各入力フィールドをクリア
          NameTextBox.Text       = string.Empty;
          EmailTextBox.Text      = string.Empty;
          AgeNumericUpDown.Value = 20;  // デフォルト値に戻す
 
          // チェックボックスをすべて未選択に
          var checkBoxes = this.FindControl<StackPanel>("HobbiesPanel")
                               .Children.OfType<CheckBox>();
          foreach (var checkbox in checkBoxes)
          {
             checkbox.IsChecked = false;
          }
       }
 
       // 送信ボタンを押下した時
       private async void SubmitButton_Click(object sender, RoutedEventArgs e)
       {
          // 入力値の検証
          if (string.IsNullOrWhiteSpace(NameTextBox.Text))
          {
             // 警告メッセージを表示
             var msgbox = MessageBoxManager.GetMessageBoxStandard("入力エラー", 
                                                                  "氏名を入力",
                                                                  ButtonEnum.Ok,
                                                                  Icon.Warning);
             await msgbox.ShowAsync();
             return;
          }
 
          if (string.IsNullOrWhiteSpace(EmailTextBox.Text))
          {
             // 警告メッセージを表示
             var msgbox = MessageBoxManager.GetMessageBoxStandard("入力エラー", 
                                                                  "メールアドレスを入力",
                                                                  ButtonEnum.Ok,
                                                                  Icon.Warning);
             await msgbox.ShowAsync();
             return;
          }
 
          // 送信確認のダイアログを表示
          var confirmBox = MessageBoxManager.GetMessageBoxStandard("確認",
                                                                   "入力した情報を送信しますか?",
                                                                   ButtonEnum.YesNo,
                                                                   Icon.Question);
 
          var result = await confirmBox.ShowAsync();
          if (result == ButtonResult.Yes)
          {
             // ...略 (送信処理)
 
             // 成功メッセージを表示
             var successBox = MessageBoxManager.GetMessageBoxStandard("送信完了",
                                                                      "情報を正常に送信",
                                                                      ButtonEnum.Ok,
                                                                      Icon.Success);
             await successBox.ShowAsync();
          }
       }
    }
 }