Search code examples
c#xamlxamarin.formsxamarin-forms-4

How to bind a simple Label inside ListView for Xamarin Forms?


How a very simple binding would work for Label inside ListView?

I seem to have spent hours on this but can't figure out.

What is wrong with data binding of label?

Because three rows are displayed that means Observable collection from View Model has been bound.

Am I over using x:DataType is it really needed for simple grid binding?

enter image description here

XAML file

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="Poc.ListViewGrouping.Views.LvDemo"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:Poc.ListViewGrouping.ViewModels"
    xmlns:model="clr-namespace:Poc.ListViewGrouping.Models">
    <ContentPage.Content>
        <StackLayout>
            <Label
                HorizontalOptions="CenterAndExpand"
                Text="Welcome to Abhijeet's Page Of List View!"
                VerticalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
    <ContentPage.ToolbarItems>
        <ToolbarItem Command="{Binding AddItemCommand}" Text="Add Milestone" />
    </ContentPage.ToolbarItems>
    <RefreshView x:DataType="local:Lv1Vm">
        <StackLayout BackgroundColor="Orange">
            <ListView
                x:Name="lv1"
                BackgroundColor="Green"
                ItemsSource="{Binding DS}">
                <ListView.ItemTemplate>
                    <DataTemplate x:DataType="local:Lv1Vm">
                        <ViewCell>
                            <Frame BackgroundColor="Navy">
                                <StackLayout
                                    Padding="10"
                                    x:DataType="model:LvModel"
                                    BackgroundColor="Yellow"
                                    HeightRequest="30">
                                    <!--  Does not bind at all  -->
                                    <Label BackgroundColor="Red"
                                           Text="{Binding Name}" />
                                </StackLayout>
                            </Frame>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </RefreshView>
</ContentPage>

Code Behind File

using Poc.ListViewGrouping.ViewModels;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Markup;
using Xamarin.Forms.Xaml;
namespace Poc.ListViewGrouping.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class LvDemo : ContentPage
    {
        public Lv1Vm _viewModel;

        public LvDemo()
        {
            BindingContext = _viewModel = new Lv1Vm();

            InitializeComponent();
        }
    }
}

View Model

using Poc.ListViewGrouping.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;

namespace Poc.ListViewGrouping.ViewModels
{
    public class Lv1Vm : BaseViewModel
    {
        public ObservableCollection<LvModel> DS => new ObservableCollection<LvModel>()
        {
            new LvModel{Id = 1, Name = "Hello" },
            new LvModel{Id = 2, Name="Hi"},
            new LvModel{Id = 3, Name="Good Going"},
        };

        public Lv1Vm()
        {
            Title = "Lv1";
        }
    }
}

Model

public class LvModel
{
    public string Name { get; set; }
    public int Id { get; set; }

}

Solution

  • In fact, your binding is correct, and the reason it doesn't show up is because of all rows in a ListView have the same height by default.It doesn't compute the height of your child item anymore.

    You could try to set HasUnevenRows="True"

    <ListView
                HasUnevenRows="True"
                x:Name="lv1"
                BackgroundColor="Green"
                ItemsSource="{Binding DS}">
           <ListView.ItemTemplate>
                  <DataTemplate x:DataType="local:Lv1Vm">
                      <ViewCell>
                          <Frame BackgroundColor="Navy">
                              <StackLayout
                                    Padding="10"
                                    x:DataType="model:LvModel"
                                    BackgroundColor="Yellow"
                                    HeightRequest="30">
                                    <!--  Does not bind at all  -->
                                  <Label BackgroundColor="Red"
                                           Text="{Binding Name}" />
                              </StackLayout>
                          </Frame>
                      </ViewCell>
                </DataTemplate>
          </ListView.ItemTemplate>
    </ListView>
    

    or set RowHeight

    <ListView
                HasUnevenRows="False"
                RowHeight="80"
                x:Name="lv1"
                BackgroundColor="Green"
                ItemsSource="{Binding DS}">
                <ListView.ItemTemplate>
                    <DataTemplate x:DataType="local:Lv1Vm">
                        <ViewCell>
                            <Frame BackgroundColor="Navy">
                                <StackLayout
                                    Padding="10"
                                    x:DataType="model:LvModel"
                                    BackgroundColor="Yellow"
                                    HeightRequest="30">
                                    <!--  Does not bind at all  -->
                                    <Label BackgroundColor="Red"
                                           Text="{Binding Name}" />
                                </StackLayout>
                            </Frame>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
    </ListView>