Home > Back-end >  Xamarin.forms: How to get Object value from a Listview
Xamarin.forms: How to get Object value from a Listview

Time:06-04

I am placing a stepper inside a Listview. I would like to know which Item the Stepper belong to when I change it. Here is the Listview. I would like to know, when I modify the stepper's value, which EAN is part of the same ViewCell.

        <ListView x:Name="ItemsListView"
            ItemsSource="{Binding Items}"
            VerticalOptions="FillAndExpand"
            HasUnevenRows="true"
            RefreshCommand="{Binding LoadItemsCommand}"
            IsPullToRefreshEnabled="true"
            IsRefreshing="{Binding IsBusy, Mode=OneWay}"
            CachingStrategy="RecycleElement"
            ItemTapped="OnItemSelected"
              >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Padding="10" Orientation="Vertical" HorizontalOptions="FillAndExpand">
                            <Label Text="{Binding Name}" LineBreakMode="WordWrap"  FontSize="16" HorizontalOptions="FillAndExpand"  />
                            <Label Text="{Binding QuantityExpectedDisplay}" LineBreakMode="WordWrap"  FontSize="10" HorizontalOptions="FillAndExpand"  />
                            <Label Text="{Binding EAN}" LineBreakMode="WordWrap"  FontSize="10" HorizontalOptions="FillAndExpand"  />
                            <Stepper Value="{Binding QuantityDefect}" Minimum="0" Maximum="{Binding Quantity}" HorizontalOptions="FillAndExpand" ValueChanged="Stepper_ValueChanged" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

So that I can use that ean later to find the corresponding line. (In the example, I would like to find the ListItem, or at least its EAN in test, rather than putting a new one)

    private void Stepper_ValueChanged(object sender, ValueChangedEventArgs e)
    {
        ListItem test = new ListItem();//Here I'd like the ViewCell Values
        var line = viewModel.lines.Find(l => l.Ean == test.EAN);
        line.QuantityOpen = (int)e.NewValue;
    }

Thank you and have a nice day

CodePudding user response:

We generally don't recommend using this method,you can implement INotifyPropertyChanged for your the item of Items.

Suppose the item model is Item.cs, you can implement INotifyPropertyChanged as follows:

public class Item: INotifyPropertyChanged
{
    public string Name { get; set; }
    public string QuantityExpectedDisplay{ get; set; }
    public string EAN{ get; set; }

    //public int  QuantityDefect { get; set; }

    int _quantityDefect;
    public int QuantityDefect
    {
        set { SetProperty(ref _quantityDefect, value); }

        get { return _quantityDefect; }
    }

    public int Quantity { get; set; }

    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }

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

    public event PropertyChangedEventHandler PropertyChanged;
}

And in YourPage.xaml,we can do like this:

    <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Padding="10" Orientation="Vertical" HorizontalOptions="FillAndExpand">
                        <Label Text="{Binding Name}" LineBreakMode="WordWrap"  FontSize="16" HorizontalOptions="FillAndExpand"  />
                        <Label Text="{Binding QuantityExpectedDisplay}" LineBreakMode="WordWrap"  FontSize="10" HorizontalOptions="FillAndExpand"  />
                        <Label Text="{Binding EAN}" LineBreakMode="WordWrap"  FontSize="10" HorizontalOptions="FillAndExpand"  />
                        <Stepper Value="{Binding QuantityDefect}" Minimum="0" Maximum="10" Increment="1" HorizontalOptions="FillAndExpand"  />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>

Note:

Once we change the stepper's value, the value of QuantityDefect will change accordingly.

CodePudding user response:

First, see Jessie's answer for the basics of Data Binding to a list of items.

Or see example described in ListView Data Sources.


In addition, we need a way to tell viewmodel what item has changed.

MessagingCenter can do this.

MyViewModel.cs:

public MyViewModel()
{
    MessagingCenter.Subscribe<MyItem>(this, "changed", Item_Changed);
}

public ObservableCollection<MyItem> Items { get; set; }

private void Item_Changed(MyItem item)
{
    var index = Items.IndexOf(item);
    // Make sure it is mine.
    if (index >= 0)
    {
        // ...
    }
}

MyItem.cs:

int _quantityDefect;
public int QuantityDefect
{
    get => _quantityDefect;
    set
    {
        SetProperty(ref _quantityDefect, value);
        Xamarin.Forms.MessagingCenter.Send<MyItem>(this, "changed");
    }
}
  • Related