简体   繁体   中英

Retrieving ListView selected item value in Xamarin.Forms

I'm developing/learning XamarinForms. I'm using Web Api to get values and use them to populate a ListView. Now I want to get current values on ItemSelected and store them for later use, but I don't seem to work it out. I'm using the MVVM.

This is my ListView

<ListView x:Name="ProfileDetails" ItemsSource="{Binding Profiles}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout  Margin="20,0,0,0" Orientation="Horizontal" HorizontalOptions="FillAndExpand">
                     <Label Text="{Binding ProfileType}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand" TextColor="LightGray"/>
                    <Label Text="{Binding ProfileChamber}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand"  TextColor="LightGray"/>
                    <Label Text="{Binding ProfileWidhtMM}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand" TextColor="LightGray"/>
                    <Label Text="{Binding ProfilePrice}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand"  TextColor="LightGray"/>
                 </StackLayout>
             </ViewCell>
         </DataTemplate>
     </ListView.ItemTemplate>                
 </ListView>

This is the ViewModel

APIServices _apiServices = new APIServices();


private List<Profile> _profiles;

public List<Profile> Profiles
{
    get { return _profiles; }
    set
    {
        _profiles = value;
        OnPropertyChanged();
    }
}


public ICommand GetProfilesCommand
{
    get
    {
        return new Command(async () =>
        {
            Profiles = await _apiServices.GetProfilesAsync(_accessToken);
        });
    }
}

And this is my API request

public async Task<List<Profile>> GetProfilesAsync(string accessToken)
{
    var client = new HttpClient();

    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    var json = await client.GetStringAsync(Constants.GetProfilesUrl);
    var profiles = JsonConvert.DeserializeObject<List<Profile>>(json);
    return profiles;
}

And this is the Model

public long Id { get; set; }
public string ProfileType { get; set; }
public int ProfileChamber { get; set; }
public int ProfileWidhtMM { get; set; }
public double ProfilePrice { get; set; } 

In your xaml add the ItemTapped property. Can be:

ItemTapped="ProfileDetails_Selected"

Then you should have the method handling the event in your code behind as:

private void ProfileDetails_Selected(object sender, ItemTappedEventArgs e)
    {
       var myItem = e.Item ...; //from here you can get your item and store for later use
    }

Answer from Oluwasayo is correct but I see that you are using MVVM already so using this solution might be better for you, just in case if you want to keep your code-behind class clean and leave any mixing code-behind and ViewModel code for one functionality.

I don't know if you are using some MVVM framework or not, but there is a very nice and helpful behavior called EventToCommandBehavior you can use it to "translate" any event and bind it to a command in your ViewModel.

You can find implementation of it here on GitHub, you can easly include it in your project. There is a lot of other implementations from MVVM frameworks.

Steps to make this in the way I advice you are:

  1. Include that class in your project and you can use it in xaml pages.

  2. Edit VM code and add some aditional lines of code.

ViewModel code:

// Property for binding SelectedItem from ListView.
private Profile _selectedProfile;
public Profile SelectedProfile
{
    get { return _profiles; }
    set
    {
        _selectedProfile= value;
        OnPropertyChanged();
    }
}

// Command which we will use for Event to Command binding.
public DelegateCommand ItemTappedCommand{ get; private set; }

// ...
// Code inside of the ctor in VM:
ItemTappedCommand = new Command(ItemTapped);
// ...

// Method which will be executed using our command
void ItemTapped()
{
    // Here you can do whatever you want, this will be executed when
    // user clicks on item in ListView, you will have a value of tapped
    // item in SlectedProfile property
}
  1. Edit your XAML page code and add few code lines.

XAML Page:

<!-- In your page xaml header add xaml namespace to EventToCommandBehaviour class-->
xmlns:b="clr-namespace:Namespace.ToYour.EventToCommandBehaviourClass"

<ListView x:Name="ProfileDetails" ItemsSource="{Binding Profiles}"
          SelectedItem={Binding SelectedProfile}>
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Margin="20,0,0,0" Orientation="Horizontal" HorizontalOptions="FillAndExpand">
                    <Label Text="{Binding ProfileType}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand" TextColor="LightGray"/>
                    <Label Text="{Binding ProfileChamber}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand"  TextColor="LightGray"/>
                    <Label Text="{Binding ProfileWidhtMM}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand" TextColor="LightGray"/>
                    <Label Text="{Binding ProfilePrice}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand"  TextColor="LightGray"/>
                  </StackLayout>
              </ViewCell>
          </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.Behaviors>
        <b:EventToCommandBehavior EventName="ItemTapped" 
                                  Command="{Binding ItemTappedCommand}" />
    </ListView.Behaviors>               
</ListView>

Hope that this makes sense to you, using this approach your code-behind class will stay clean without mixing the code between vm and code-behind, just my tip for you.

Wishing you lots of luck with coding!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM