Kenzo_Gilead
Kenzo_Gilead

Reputation: 2439

Binding a list of object to grid

Trying to render a ListView with a grid into it. The grid contains two columns. The first one, with a button. The second one, with a Label.

Model contains two attributes. First one, a List of specific object. Second one, a string.

Finally, the label of the grid inside of listview will be binded to the one random attribute of list of object of the Model.

My best approach is:

<ListView x:Name="intervectionList"
                  ItemsSource="{Binding .}">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <Grid Padding="5">
              <Grid.RowDefinitions>
                <RowDefinition Height="20"></RowDefinition>
                <RowDefinition Height="1"></RowDefinition>
              </Grid.RowDefinitions>
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"></ColumnDefinition>
                <ColumnDefinition Width="3*"></ColumnDefinition>
              </Grid.ColumnDefinitions>

              <Button Text="Play" Grid.Row="0" Grid.Column="0" Clicked="OnLogginClicked"/>
              <Label Grid.Row="0" Grid.Column="1" Text="{Binding random_attribute}"/>
              <BoxView Color="Navy" HeightRequest="1" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"/>

            </Grid>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

CODE-BEHIND:

public Intervection()
        {
            InitializeComponent();
            var obj= new Model();
            this.BindingContext = prueba.List_of_object;
        }

public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void RaiseOnPropertyChange([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    public ViewModel()
    {
        _viewmodel = new ViewModel();
    }

    private ViewModel _viewmodel;

    private string _attribute1;

    public string Attribute1
    {
        get { return _attribute1; }
        set { _attribute1= value; RaiseOnPropertyChange(); }
    }
.............
    }

public class Model
    {
        public List<obj> Intervencion;
        public string attribute2;
// Helpers...
}

That is not rendering anything.

I tried successive approaches. Coming from Basic ListView with string, ListView of object,... and so on. The problem is coming from when I insert the grid.

After check Stackoverflow. I found this link Create Grid from Code-Behind, but this is not serving to my purpose because I can´t re-write the view model. (I, even, tried to coded it).

As usual, thanks mates.

Upvotes: 1

Views: 3055

Answers (2)

Kenzo_Gilead
Kenzo_Gilead

Reputation: 2439

Finally I got it. The xaml needed for it is the next one (you can complet all code coming from the code´s question). Posted just in case you all want to use another approach. Proper answer (more elegant) is @Rohit´s answer.

<ContentPage.Resources>
      <ResourceDictionary>
        <Color x:FactoryMethod="FromHex" x:Key="fondoBlancoPalido">
          <x:Arguments>
            <x:String>#F2F2F2</x:String>
          </x:Arguments>
        </Color>
      </ResourceDictionary>
    </ContentPage.Resources>

<ListView x:Name="listView" ItemsSource="{Binding .}" BackgroundColor="{StaticResource fondoBlancoPalido}">
        <ListView.ItemTemplate>
          <DataTemplate>
            <ViewCell>
              <ViewCell.View>
                <Grid Padding="5">
                  <Grid.RowDefinitions>
                    <RowDefinition Height="60"></RowDefinition>
                    <RowDefinition Height="60"></RowDefinition>
                    <RowDefinition Height="10"></RowDefinition>
                  </Grid.RowDefinitions>
                  <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="1*"></ColumnDefinition>
                    <ColumnDefinition Width="2*"></ColumnDefinition>
                    <ColumnDefinition Width="3*"></ColumnDefinition>
                  </Grid.ColumnDefinitions>

                  <Button Grid.Row="0" Grid.Column="0" Clicked="OnStartClicked" Image="play.png" BackgroundColor="Transparent" HorizontalOptions="Center" Grid.RowSpan="2"/>
                  <Label Grid.Row="0" Grid.Column="1" Text="Hora de Inicio: " XAlign="Center" YAlign="Center" TextColor="Black" FontAttributes="Bold"/>
                  <Label Grid.Row="0" Grid.Column="2" Text="{ Binding attribute3 }" XAlign="Center" YAlign="Center" TextColor="Black"/>
                  <Label Grid.Row="1" Grid.Column="1" Text="Encargado de la Tarea: " XAlign="Center" YAlign="Center" TextColor="Black" FontAttributes="Bold"/>
                  <Label Grid.Row="1" Grid.Column="2" Text="{ Binding attribute4 }" XAlign="Center" YAlign="Center" TextColor="Black"/>
                  <BoxView Color="Navy" HeightRequest="2" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"/>
                </Grid>
              </ViewCell.View>
            </ViewCell>
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>

Upvotes: 0

Rohit Vipin Mathews
Rohit Vipin Mathews

Reputation: 11787

I have added the VerticalOptions to the Listview and Grid. I have created a viewmodel in which I have one property, the list of items. The viewmodel also implements INotifyPropertyChanged.

You can read about INotifyPropertyChanged here.

The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed.

XAML :

<ListView ItemsSource="{Binding MyObservableCollection}" VerticalOptions="FillAndExpand">
    <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
          <Grid Padding="5" VerticalOptions="Fill">
            <Grid.RowDefinitions>
              <RowDefinition Height="20"></RowDefinition>
              <RowDefinition Height="1"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="1*"></ColumnDefinition>
              <ColumnDefinition Width="3*"></ColumnDefinition>
            </Grid.ColumnDefinitions>

            <Button Text="Play" Grid.Row="0" Grid.Column="0"/>
            <Label Grid.Row="0" Grid.Column="1" Text="{Binding .}"/>
            <BoxView Color="Navy" HeightRequest="1" Grid.Row="1" 
                     Grid.Column="0" Grid.ColumnSpan="2"/>

          </Grid>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>

ViewModel :

public class ListViewWithGridViewModel : INotifyPropertyChanged
{
    private ObservableCollection<string> _myObservableCollection;

    public ListViewWithGridViewModel()
    {
        MyObservableCollection = new ObservableCollection<string>(new List<string> { "abc", "xyz", "pqr", "aaa", "abc", "xyz", "pqr", "aaa", "abc", "xyz", "pqr", "aaa" });
    }

    public ObservableCollection<string> MyObservableCollection
    {
        get { return _myObservableCollection; }
        set
        {
            _myObservableCollection = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

XAML.cs :

public partial class ListViewWithGrid : ContentPage
{
    public ListViewWithGrid()
    {
        InitializeComponent();
        BindingContext = new ListViewWithGridViewModel();
    }
}

Upvotes: 6

Related Questions