当列表中的项目很少时,如何将ListView项目与屏幕底部对齐?

当列表中的项目很少时,如何将ListView项目与屏幕底部对齐?,listview,xamarin.forms,Listview,Xamarin.forms,我想要一个Xamarin.Forms列表视图,它从下到上显示它的元素,这样当项目很少时,元素就会显示在列表视图的底部。请参见图中的说明。这是否可以在不必手动设置ListView的HeightRequest的情况下实现?(如果需要手动设置HeightRequest,那么当我使用hasLows=true时,如何计算ListView子元素的高度?) 下面是我希望它的外观(左边的项目很少,右边的项目很多) 以下是ListView在项目较少时的正常工作方式供参考: 我会选择一个网格,其中两行定义为“*”

我想要一个Xamarin.Forms列表视图,它从下到上显示它的元素,这样当项目很少时,元素就会显示在列表视图的底部。请参见图中的说明。这是否可以在不必手动设置ListView的HeightRequest的情况下实现?(如果需要手动设置HeightRequest,那么当我使用
hasLows=true
时,如何计算ListView子元素的高度?)

下面是我希望它的外观(左边的项目很少,右边的项目很多)

以下是ListView在项目较少时的正常工作方式供参考:


我会选择一个网格,其中两行定义为“*”或您想要的像素高度,底部定义为“自动”,listview垂直选项设置为“结束”。

如果
listview
不是强制性的,并且您只需要一个具有模板支持的可重复控件,您可以使用。由于它使用
StackLayout
作为面板,因此它只能扩展到所需的高度。所以,你不需要计算它的高度请注意
ItemsControl
具有非常基本的虚拟化行为(回收)-因此,如果您有很多项目,则必须修改该控件以支持虚拟化。

其次,您可以扩展
网格
,根据底部内容大小自动将第二个
行定义
设置为
自动
星型
。i、 e.默认情况下,将其保持为
自动
,但如果内容大小大于视口高度的50%,则将
行定义
重置为
星型
。例如,您可以创建自定义的拆分网格,如下所示:

public class SplitterGrid : Grid
{
    public SplitterGrid()
    {
        RowDefinitions = new RowDefinitionCollection() 
        { 
            new RowDefinition { Height = GridLength.Star }, 
            new RowDefinition { Height = GridLength.Auto }
        };
    }

    void Content2_SizeChanged(object sender, EventArgs e)
    {
        if (Height == 0 && Width == 0)
            return;

        Content2.SizeChanged -= Content2_SizeChanged;
        if (Content2.Height > Height / 2)
            RowDefinitions[1].Height = GridLength.Star;
        else
            RowDefinitions[1].Height = GridLength.Auto;
    }

    public static readonly BindableProperty Content1Property =
        BindableProperty.Create(
        "Content1", typeof(View), typeof(SplitterGrid),
        defaultValue: null, propertyChanged: OnContent1Changed);

    public View Content1
    {
        get { return (View)GetValue(Content1Property); }
        set { SetValue(Content1Property, value); }
    }

    private static void OnContent1Changed(BindableObject bindable, object oldValue, object newValue)
    {
        ((SplitterGrid)bindable).OnContent1ChangedImpl((View)oldValue, (View)newValue);
    }

    void OnContent1ChangedImpl(View oldValue, View newValue)
    {
        if (oldValue == null)
            Children.Add(Content1);
    }

    public static readonly BindableProperty Content2Property =
        BindableProperty.Create(
        "Content2", typeof(View), typeof(SplitterGrid),
        defaultValue: null, propertyChanged: OnContent2Changed);

    public View Content2
    {
        get { return (View)GetValue(Content2Property); }
        set { SetValue(Content2Property, value); }
    }

    private static void OnContent2Changed(BindableObject bindable, object oldValue, object newValue)
    {
        ((SplitterGrid)bindable).OnContent2ChangedImpl((View)oldValue, (View)newValue);
    }

    void OnContent2ChangedImpl(View oldValue, View newValue)
    {
        if (oldValue == null)
        {
            Children.Add(Content2);
            Content2.SizeChanged += Content2_SizeChanged;
            Grid.SetRow(Content2, 1);
        }
        else 
            Content2.SizeChanged -= Content2_SizeChanged;
    }
}
并且,使用情况如下所示:

<local:SplitterGrid Margin="0,20,0,0">
    <local:SplitterGrid.Content1>
        <ContentView Padding="10" BackgroundColor="#E4E4E4">
            <Label Text="This page contains about 3 items." />
        </ContentView>
    </local:SplitterGrid.Content1>
    <local:SplitterGrid.Content2>
        <ScrollView VerticalOptions="End">
            <local:ItemsControl>
                <local:ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Label FontAttributes="Bold" FontSize="40" Text="{Binding .}" />
                    </DataTemplate>
                </local:ItemsControl.ItemTemplate>
                <local:ItemsControl.ItemsSource>
                    <x:Array Type="{x:Type x:String}">
                        <x:String>Item 1</x:String>
                        <x:String>Item 2</x:String>
                        <x:String>Item 3</x:String>
                    </x:Array>
                </local:ItemsControl.ItemsSource>
            </local:ItemsControl>
        </ScrollView>
    </local:SplitterGrid.Content2>
</local:SplitterGrid>

项目1
项目2
项目3

不幸的是,这似乎不起作用。在
Auto
行中,ListView的扩展似乎优先于
*
行的扩展。结果和我开始时差不多。谢谢,ItemsControl运行得非常好(除了a)。我相信,这应该很容易修复;通过在ItemsSource change listener中添加clear方法(如果新的集合计数小于以前),是的,我链接到一个修复它的PR。