.NET Maui根据显示区域动态更改布局

mgdq6dx1  于 2023-02-06  发布在  .NET
关注(0)|答案(1)|浏览(235)

我有一个包含三个区域的页面(每个VerticalStackLayout包含一个LabelFrame包含一个CollectionView),底部有两个Buttons。每个区域可能显示,也可能不显示,具体取决于基础条件。无论哪个区域可见(三个、两个或一个--可以是anytwo或anyone)应该扩展到填充可用的视图空间,但是我还没有找到XAML元素的正确组合来实现这一点。
我现在有这样的结构:

<Grid
    ColumnDefinitions="*,*"
    RowDefinitions="*,60">
    <VerticalStackLayout Grid.Row="0" Grid.ColumSpan="2">
        <VerticalStackLayout IsVisible="{Binding ConditionA}">
            <Label Text="States" />
            <Frame HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
        <VerticalStackLayout IsVisible="{Binding ConditionB}">
            <Label Test="Topics" />
            <Frame HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
        <VerticalStackLayout IsVisible="{Binding ConditionC}">
            <Label Text="Activities" />
            <Frame HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
    </VerticalStackLayout>
    <Button Grid.Row="1" Grid.Column="0" />
    <Button Grid.Row="1" Grid.Column="1" />
</Grid>

如果Frame上没有HeightRequestCollectionView就会扩展到整个页面,并在页面底部溢出。编程管理HeightRequest的想法(即,为显示的任何区域计算适当的高度)感觉并不正确。似乎扩展应该由XAML元素根据可用空间处理;例如HorizontalOptions="CenterAndExpand"或其它。
因此,当所有三个区域都可见时,它们应该在页面上从上到下显示晚间:

List A
+-----------------------------+
|                             |
|                             |
|                             |
|                             |
|                             |
|                             |
+-----------------------------+

           List B
+-----------------------------+
|                             |
|                             |
|                             |
|                             |
|                             |
|                             |
+-----------------------------+

           List C
+-----------------------------+
|                             |
|                             |
|                             |
|                             |
|                             |
|                             |
+-----------------------------+

   +----------+ +-----------+
   |  Button  | |  Button   |
   +----------+ +-----------+

但如果只有两个区域,则应扩展区域的高度以在视图空间中平衡:

List A
+------------------------------+
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
+------------------------------+

           List C
+------------------------------+
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
+------------------------------+

   +----------+ +-----------+
   |  Button  | |  Button   |
   +----------+ +-----------+

或者,如果只显示一个区域,则该区域应填满可用的视图空间:

List B
+------------------------------+
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
+------------------------------+

   +----------+ +-----------+
   |  Button  | |  Button   |
   +----------+ +-----------+

更新:以下是我根据答案所做的。
XAML语言

<Grid
    ColumnDefinitions="*,*">
    <Grid.RowDefinitions>
        <RowDefinition x:Name="MainArea" Height="*" />
        <RowDefinition x:Name="ButtonArea" Height="60" />
    </Grid.RowDefinitions>
    <VerticalStackLayout Grid.Row="0" Grid.ColumSpan="2">
        <VerticalStackLayout x:Name="StatesFilter" IsVisible="{Binding ConditionA}">
            <Label Text="List A" />
            <Frame x:Name="StatesFrame" HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
        <VerticalStackLayout x:Name="TopicsFilter" IsVisible="{Binding ConditionB}">
            <Label Test="List B" />
            <Frame x:Name="TopicsFrame" HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
        <VerticalStackLayout x:Name="ActivitiesFilter" IsVisible="{Binding ConditionC}">
            <Label Text="List C" />
            <Frame x:Name="ActivitiesFrame" HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
    </VerticalStackLayout>
    <Button Grid.Row="1" Grid.Column="0" />
    <Button Grid.Row="1" Grid.Column="1" />
</Grid>

代码隐藏

protected override void OnSizeAllocated(double width, double height)
{
    base.OnSizeAllocated(width, height);

    // This is called twice, once with -1, -1 then the next call with
    // the actual width and height.
    if (Height > 0)
    {
        AdjustRegionHeight(height);
    }
}

private void AdjustRegionHeight(double pageHeight)
{
    double frameHeight;
    double bottomSpace = 44; 

    int cnt = 0;
    cnt += (StatesFilter.IsVisible) ? 1 : 0;
    cnt += (TopicsFilter.IsVisible) ? 1 : 0;
    cnt += (ActivitiesFilter.IsVisible) ? 1 : 0;

    double fullHeight = pageHeight - ButtonArea.Height.Value;
    frameHeight = (fullHeight / cnt) - bottomSpace;

    StatesFrame.HeightRequest = (StatesFilter.IsVisible) ? frameHeight : 0;
    TopicsFrame.HeightRequest = (TopicsFilter.IsVisible) ? frameHeight : 0;
    ActivitiesFrame.HeightRequest = (ActivitiesFilter.IsVisible) ? frameHeight : 0;
}
hsgswve4

hsgswve41#

用编程方式管理HeightRequest(即,为显示的区域计算适当的高度)的想法并不正确,似乎扩展应该由XAML元素根据可用空间来处理;
相反,编程地管理HeightRequest的想法更有可能实现。
根据您的代码,我不知道{Binding ConditionA}背后的代码。因此,要实现此需求:* * 单击按钮更改布局**:
. xaml:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="MauiApp1.NewPage1" 
             Title="NewPage1">
  <Grid ColumnDefinitions="*,*" RowDefinitions="*,60">
       <VerticalStackLayout Grid.Row="0" Grid.ColumnSpan="2">
              <VerticalStackLayout x:Name="ListA" IsVisible="true">
                     <Label Text="List A" />
                     <Frame x:Name="FrameA" HeightRequest="150">
                            <CollectionView />
                     </Frame>
              </VerticalStackLayout>
              <VerticalStackLayout x:Name="ListB" IsVisible="true">
                     <Label Text="List B" />
                     <Frame x:Name="FrameB" HeightRequest="150">
                            <CollectionView />
                     </Frame>
              </VerticalStackLayout>
              <VerticalStackLayout x:Name="ListC" IsVisible="true">
                     <Label Text="List C" />
                     <Frame x:Name="FrameC" HeightRequest="150">
                            <CollectionView />
                     </Frame>
              </VerticalStackLayout>
       </VerticalStackLayout>
       <Button Grid.Row="1" Grid.Column="0" Clicked="onlyOne"/>
       <Button Grid.Row="1" Grid.Column="1" Clicked="Two"/>
  </Grid>
</ContentPage>

. xaml. cs:

public partial class NewPage1 : ContentPage
{
    public NewPage1()
    {
        InitializeComponent();
    }

    private void onlyOne(object sender, EventArgs e)
    {
        //change the state of IsVisible of VerticalStackLayout        
        ListB.IsVisible = false;
        ListA.IsVisible = false;
        ListC.IsVisible = true;

        FrameC.HeightRequest = 450;
    }

    private void Two(object sender, EventArgs e)
    {
        ListC.IsVisible = false;
        ListB.IsVisible = true;
        ListA.IsVisible = true;
        
        FrameA.HeightRequest = 225;
        FrameB.HeightRequest = 225;
    }
}

第一个按钮表示仅显示一个区域(列表C)。第二个按钮表示仅显示两个区域(列表A和B)。
回到您的情况,ConditionA/B/C change相当于上面的按钮被点击,您可以在Button. Clicked中添加代码逻辑来实现ConditionA/B/C change的功能。

相关问题