listviewxamarinxamarin.formsobservablecollectionxamarin.forms.entry

How can I pass an object parameter to an Entry event in Xamarin.Forms?


I have implemented a ListView that is binded to an ObservableCollection and I need to update each item when the entry fields are changed. I am using the completed event but it only passes the entry value to the completed event function and I don't know what object I am editing.

Is there any way to pass an object parameter to these entry events so that I can update the correct object? Or is there a better approach to doing this?

UPDATE

This is my list view code

<ListView 
            x:Name="DrawReturnList" 
            RowHeight="65" 
            BackgroundColor="#ffffff"
            CachingStrategy="RecycleElement" 
            ItemsSource="{Binding SCSDraw}"
            ItemSelected = "OnItemTapped"   
            IsPullToRefreshEnabled="false"
            Margin="0, -10, 0, 0">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout VerticalOptions="FillAndExpand"
                                     HorizontalOptions="FillAndExpand"
                                     Orientation="Vertical"
                                     Padding="10">

                            <StackLayout Orientation="Horizontal">
                              <StackLayout HorizontalOptions="FillAndExpand" WidthRequest="90" Padding="0, 10, 0, 0">
                                <Label Text="{Binding PubDateShort3}" FontSize="18"/>
                              </StackLayout>

                              <StackLayout HorizontalOptions="FillAndExpand" Orientation="Horizontal">

                                    <Grid HorizontalOptions="FillAndExpand" ColumnSpacing="0" RowSpacing="0">
                                      <Grid.RowDefinitions>
                                        <RowDefinition Height="*" />

                                      </Grid.RowDefinitions>
                                      <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*" />
                                        <ColumnDefinition Width="*" />
                                        <ColumnDefinition Width="*" />
                                      </Grid.ColumnDefinitions>

                                      <StackLayout Grid.Row="0" Grid.Column="0" Padding="0, 10, 0, 0">
                                        <Label Text="{Binding InitialDraw}" FontSize="18"/>
                                      </StackLayout>
                                      <StackLayout  Grid.Row="0" Grid.Column="1">
                                            <Entry IsEnabled="{Binding ACLockFL, Converter={StaticResource not}}" Keyboard="Numeric" Placeholder="Draw" Text="{Binding Draw, Mode=TwoWay}" VerticalOptions="Center"/>
                                      </StackLayout> <!-- end Draw -->
                                      <StackLayout Grid.Row="0" Grid.Column="2">
                                            <Entry IsEnabled="{Binding ACLockFL, Converter={StaticResource not}}" Keyboard="Numeric" Placeholder="Returns" Text="{Binding Returns, Mode=TwoWay}" VerticalOptions="Center"/>
                                      </StackLayout> <!-- end Return -->
                                    </Grid>


                              </StackLayout>
                            </StackLayout><!-- end input group -->



                        </StackLayout> <!-- end Draw & Return Section-->
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView> <!-- end list view -->

This is binded to an Observable Collection that is in my ViewModel.

What I need to do is be able to edit each individual list item with its respective entry and have that be saved to its respective object. I tried the completed event on the Entry but I cant pass a parameter to this. How should I approach this?

UPDATE

MODEL

using System;
using System.ComponentModel;
using Collector.Helpers;

namespace Collector
{
    public class AC_SCSDraw : EntityData, INotifyPropertyChanged
    {   
    private int draw;
    private int returns;

    public decimal CarrierID { get; set; }
    public decimal RspID { get; set; }
    public string RspName { get; set; }
    public decimal SCSDrawID { get; set; }
    public decimal PubID { get; set; }
    public string PubDesc { get; set; }
    public string WeekDay { get; set; }
    public DateTime PubDate { get; set; }
    public string PubDateShort3 { get; set; }
    public int Draw
    {
        get { return draw; }
        set
        {
            draw = value;
            OnPropertyChange("Draw");
        }
    }
    public int Returns 
    {
        get { return returns; }
        set
        {
            returns = value;
            OnPropertyChange("Returns");
        }
    }
    public int InitialDraw { get; set; }
    public bool ACLockFL { get; set; }



    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChange(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}
}

ViewMODEL

ObservableCollection<AC_SCSDraw> scsDraw = new ObservableCollection<AC_SCSDraw>();
    public ObservableCollection<AC_SCSDraw> SCSDraw
    {
        get { return scsDraw; }
        set
        {
            scsDraw = value;
            OnPropertyChanged("SCSDraw");
        }
    }
public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        var changed = PropertyChanged;
        if (changed != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Solution

  • If I understood you correctly, you want to change the value in an entry and save this changes depending on the underlying object.

    One way to detect the change in the entry is, you need to check the changes in the property of your item-model (with the help of the INotifyPropertyChanged). Either directly in the Set-part or you register the OnPropertyChanged-Event of your item-model.

    Here is an example for your property Draw (first entry)

    public string Draw
    {
        get { return _draw; }
        set
        {
            if (value == _draw) return;
    
            _draw= value;
            RaisePropertyChanged("Draw");
    
            // Here you can save your object
        }
    }
    private string _draw;
    

    The disadvantage is, that you save your object on every charachter-change in the entry (that's not really smooth).

    My suggestion is, that you either add a "save" button with a command (on this command you can send an additional command-property -> your item)

    Or you implement a separate page to modify each item (this is the clearest way from to point of the user interface). But it depends on your use case.