How to get a ListView to behave inside a StackLayout?

I'm struggling with getting my layout to behave. I'm trying to create a page that shows a person along with a list of their children that lets them update how many children they have.

Here's what I have currently:

<StackLayout Orientation="Vertical" HorizontalOptions="Center">
  <controls:BindablePicker x:Name="pkrChildren" ItemsSource="{Binding ChildrenItems}" Title="Num. Children" SelectedItem="{Binding Path=CurrentPerson.NumChildren, Mode=TwoWay}" HorizontalOptions="Center" />
  <ListView x:Name="lvChildren" ItemsSource="{Binding Path=CurrentPerson.Children}" HorizontalOptions="Center" SeparatorVisibility="None">
    <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
          <ViewCell.View>
            <Grid>
              <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
              </Grid.ColumnDefinitions>
              <controls:BindablePicker Title="Age" Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Ages}"  SelectedItem="{Binding Path=ChildModel.Age, Mode=TwoWay}" HorizontalOptions="End" />
              <controls:BindablePicker Title="Units" Grid.Row="0" Grid.Column="1" ItemsSource="{Binding AgeUnits}" SelectedItem="{Binding Path=ChildModel.Unit, Mode=TwoWay}" HorizontalOptions="Start" />
            </Grid>
          </ViewCell.View>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
  <Label Text="More Details Below" FontAttributes="Bold" HorizontalTextAlignment="Center" />
</StackLayout>

This pushes the "More Details Below" label to the bottom of the page. What I'm wanting is the ListView to take up the minimum amount of vertical space as possible. For example, if the person has one child it'll show one row with their age, then the "More Details Below" table should be directly beneath it (no whitespace).

I'm using MVVM with Fody:

namespace Test.ViewModels
{
    [ImplementPropertyChanged]
    public class PeopleEntryViewModel
    {
        public IList<string> ChildrenItems { get; private set; }
        public CompanyModel CompanyModel { get; set; }
        public ChildEntryViewModel CurrentPerson { get; set; }

        public PeopleEntryViewModel()
        {
            Initialize();
        }

        public PeopleEntryViewModel(object param)
        {
            Initialize();

            var company = param as CompanyModel;
            CompanyModel = company;

            // We need at least one hole to load the view.
            if (CompanyModel.Employees.Count == 0)
            {
                CompanyModel.Employees.Add(new PersonModel());
            }
            CurrentPerson = new ChildEntryViewModel(CompanyModel.Employees[0]);
        }

        private void Initialize()
        {
            ChildrenItems = new List<string> { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
        }
    }
}

namespace Test.ViewModels
{
    [ImplementPropertyChanged]
    public class ChildEntryViewModel
    {
    private string _NumChildren;
    public string NumChildren
    {
        get
        {
        if (Children == null)
        {
            return null;
        }
        return Children.Count.ToString();
        }
        set
        {
        if (NumChildren != value)
        {
            _NumChildren = value;
            AdjustChildren(Convert.ToInt32(_NumChildren));
        }
        }
    }
    public string ChildNum { get; set; }
    public ObservableCollection<ChildViewModel> Children { get; set; }

    public ChildEntryViewModel()
    {
        Initialize();
    }

    public ChildEntryViewModel(object param)
    {
        var person = param as PersonModel;
        List<ChildViewModel> pvms = new List<ChildViewModel>();
        foreach (ChildModel childModel in person.Children)
        {
        pvms.Add(new ChildViewModel(childModel));
        }
        Children = new ObservableCollection<ChildViewModel>(pvms);
    }

    private void Initialize()
    {
    }

    private void AdjustChildren(int newNumChildren)
    {
        int numToCreate = newNumChildren - Children.Count;
        for (int i = 0; i < numToCreate; i++)
        {
        Children.Add(new ChildViewModel());
        }

        int numToRemove = Children.Count - newNumChildren;
        int idxToRemove = Children.Count - 1;
        for (int i = 0; i < numToRemove; i++)
        {
        Children.RemoveAt(idxToRemove--);
        }
    }
    }
}

namespace Test.ViewModels
{
    [ImplementPropertyChanged]
    public class ChildViewModel
    {
    public IList<string> Ages { get; private set; }
    public ObservableCollection<string> AgeUnits { get; private set; }
    public ChildModel ChildModel { get; set; }

    public ChildViewModel()
    {
        Initialize();
    }
    public ChildViewModel(object param)
    {
        Initialize();

        var childModel = param as ChildModel;
        ChildModel = childModel;
    }
    private void Initialize()
    {
        Ages = new List<string>();
        for (int i = 1; i < 125; i++)
        {
        Ages.Add(i.ToString());
        }
        AgeUnits = new ObservableCollection<string>(new List<string> { "Years", "Months", "Days" });
    }
    }
}

Any help would be greatly appreciated. Thanks.
- Ed.

Sign In or Register to comment.