WinUI3 メモ レイアウト - DrumMidiEditor/DrumMidiEditorApp GitHub Wiki

Grid

レイアウトの更新

コードから直接更新

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition x:Name="_PlayerRightColumn" 
            Width="{x:Bind ConfigPlayer.PlayerLayoutSize, Mode=TwoWay}" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
        <RowDefinition x:Name="_PlayerBottomRow" 
            Height="{x:Bind ConfigPlayer.PlayerLayoutSize, Mode=TwoWay}" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <local:PageMenuBar x:Name="_PageMenuBar" 
        Grid.Row="0" 
        Grid.Column="0" 
        Grid.ColumnSpan="2" />

    <local:PageNavigation x:Name="_PageNavigation" 
        Grid.Row="1" 
        Grid.RowSpan="1"
        Grid.Column="0"
        Grid.ColumnSpan="2" />
    
    <psurface:PagePlayer x:Name="_PagePlayer" 
        Grid.Row="2" 
        Grid.RowSpan="1"
        Grid.Column="0"
        Grid.ColumnSpan="2" />

    <local:PageStatusBar x:Name="_PageStatusBar" 
        Grid.Row="3" 
        Grid.Column="0" 
        Grid.ColumnSpan="2" />

</Grid>
public void UpdateGridLayout()
{
    try
    {
        int row;
        int rowspan;
        int col;
        int colspan;

        switch ( ConfigPlayer.PlayerLayoutModeSelect )
        {
            case ConfigPlayer.PlayerLayoutMode.Right:
                row     = 1;
                rowspan = 2;
                col     = 1;
                colspan = 1;
                break;
            case ConfigPlayer.PlayerLayoutMode.Bottom:
                row     = 2;
                rowspan = 1;
                col     = 0;
                colspan = 2;
                break;
            default:
                return;
        }

        // x:Bind経由では更新できなかったので直接設定
        Grid.SetRowSpan     ( _PageNavigation, rowspan );
        Grid.SetColumnSpan  ( _PageNavigation, colspan );

        Grid.SetRow         ( _PagePlayer, row );
        Grid.SetRowSpan     ( _PagePlayer, rowspan );
        Grid.SetColumn      ( _PagePlayer, col );
        Grid.SetColumnSpan  ( _PagePlayer, colspan );
    }
    catch ( Exception e )
    {
        Log.Error( $"{Log.GetThisMethodName}:{e.Message}" );
    }
}

下にプレイヤー表示
image

右にプレイヤー表示
image

RelativePanel

現状、別ウィンドウを作成できないので、RelativePanel を使用して
画面内で移動できるパネルを作成する。

image
  • メインページ側で、RelativePanel を使用して、レイアウトを設定
<RelativePanel>

    <local1:PageMenuBar x:Name="_PageMenuBar" 
        RelativePanel.AlignTopWithPanel="True"
        RelativePanel.AlignLeftWithPanel="True"
        RelativePanel.AlignRightWithPanel="True" />

    <local3:PageNavigation x:Name="_PageNavigation" 
        RelativePanel.Below="_PageMenuBar"
        RelativePanel.Above="_PageStatusBar"
        RelativePanel.AlignLeftWithPanel="True"
        RelativePanel.AlignRightWithPanel="True" />

    <local2:PageStatusBar x:Name="_PageStatusBar" 
        RelativePanel.AlignBottomWithPanel="True"
        RelativePanel.AlignLeftWithPanel="True"
        RelativePanel.AlignRightWithPanel="True" />

    <local4:PagePlayer x:Name="_PagePlayer"
        RelativePanel.AlignTopWithPanel="True"
        RelativePanel.AlignBottomWithPanel="True"
        RelativePanel.AlignLeftWithPanel="True"                                
        RelativePanel.AlignRightWithPanel="True"
        Visibility="{x:Bind ConfigPlayer.DisplayPlayerVisibility, Mode=OneWay}" />

</RelativePanel>

RelativePanelの指定方法

属性名 設定内容
Align~WithPanel Trueで、グリッド内の左右上下に引っ付ける
Align~With 入力したアイテム名の左右上下に配置
Above 入力したアイテム名の上に配置
Below 入力したアイテム名の下に配置
LeftOf 入力したアイテム名の左に配置
RightOf 入力したアイテム名の右に配置
  • 画面内で移動できるパネルの定義
<Page
    PointerPressed="Page_PointerPressed"
    PointerMoved="Page_PointerMoved"
    PointerReleased="Page_PointerReleased"
    PointerCaptureLost="Page_PointerReleased"
    PointerCanceled="Page_PointerReleased"
    HorizontalAlignment="Left"
    VerticalAlignment="Top"
    Background="#00000000">
</Page>
/// <summary>
/// 表示位置調整用マージン
/// </summary>
private Thickness _PageMargin = new();

/// <summary>
/// マウスアクション
/// </summary>
private enum EActionState : int
{
	None = 0,
	PlayerMove,
	PlayerOff,
}

/// <summary>
/// マウスアクション状態
/// </summary>
private EActionState _ActionState = EActionState.None;

/// <summary>
/// ページ移動前の位置
/// </summary>
private Point _BeforePos = new();

/// <summary>
/// マウスダウン処理
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void Page_PointerPressed( object sender, PointerRoutedEventArgs args )
{
	if ( _ActionState != EActionState.None )
	{
		return;
	}

	// ページ内ではなく、メインページ基準でのマウスの入力情報を取得する
	var p = args.GetCurrentPoint( ControlAccess.PageEditerMain );
//	var p = args.GetCurrentPoint( sender as FrameworkElement );

	if ( p.Properties.IsLeftButtonPressed )
	{
		// フォーム移動
		_BeforePos = p.Position;

		_ActionState = EActionState.PlayerMove;
	}
        else if ( p.Properties.IsRightButtonPressed )
	{
		// 非表示
		DrawSet.DisplayPlayer = false;
		Config.EventUpdatePlayerDisplay();

		_ActionState = EActionState.None;
	}
}

/// <summary>
/// マウス移動処理
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void Page_PointerMoved( object sender, PointerRoutedEventArgs args )
{
	if ( _ActionState == EActionState.None )
	{
		return;
	}

	// ページ内ではなく、メインページ基準でのマウスの入力情報を取得する
	var p = args.GetCurrentPoint( ControlAccess.PageEditerMain );
//	var p = args.GetCurrentPoint( sender as FrameworkElement );

	switch ( _ActionState )
	{
		case EActionState.PlayerMove:
			SetPagePosition( p.Position );
			break;
        }
}

/// <summary>
/// マウスアップ処理
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void Page_PointerReleased( object sender, PointerRoutedEventArgs args )
{
	if ( _ActionState == EActionState.None )
	{
		return;
	}

	// ページ内ではなく、メインページ基準でのマウスの入力情報を取得する
	var p = args.GetCurrentPoint( ControlAccess.PageEditerMain );
//	var p = args.GetCurrentPoint( sender as FrameworkElement );

	switch ( _ActionState )
	{
		case EActionState.PlayerMove:
			SetPagePosition( p.Position );
			break;
        }

	_ActionState = EActionState.None;
}


/// <summary>
/// プレイヤー表示位置設定
/// </summary>
/// <param name="aMousePoint"></param>
private void SetPagePosition( Point aMousePoint )
{
	_PageMargin.Left	+= aMousePoint.X - _BeforePos.X;
	_PageMargin.Top		+= aMousePoint.Y - _BeforePos.Y;

	_BeforePos = aMousePoint;

	Margin = _PageMargin;
}

VariableSizedWrapGrid

https://docs.microsoft.com/ja-jp/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.variablesizedwrapgrid?view=windows-app-sdk-1.1

テーブル表示の1つ

<VariableSizedWrapGrid 
   Orientation="Horizontal" 
   MaximumRowsOrColumns="2"
   Width="200"
   HorizontalAlignment="Left"
   ItemHeight="64"
   ItemWidth="100" >

    <NumberBox />
    <Button  />

</VariableSizedWrapGrid>
image
  • アイテムサイズは固定の為、最小単位のアイテムサイズを決め
    各要素にセル結合数を指定してサイズを調整する。
VariableSizedWrapGrid.ColumnSpan="2"  
VariableSizedWrapGrid.RowSpan="2"  
  • Width または Height を指定していない場合
    サイズを小さくしたときに各要素がラップされる。
image image
⚠️ **GitHub.com Fallback** ⚠️