Как перейти на другую страницу из события нажатия кнопки и передать выбранные элементы listview в качестве аргумента?

#c# #xamarin.forms

#c# #xamarin.forms

Вопрос:

Я пишу приложение для Android в формах Xamarin. Я хочу перемещать пользователя с одной страницы на другую, когда пользователь нажимает кнопку «EditList» (среднюю), но в то же время я хочу передать аргумент определенного типа: «ShoppingList», который я получаю из события ItemSelected в ListView, чтобы отобразить его содержимое на следующей странице.

Проблема в том, что единственный способ получить это значение — это щелкнуть элемент в listview. Как я могу получить значение щелчка элемента listview изнутри кнопки, без предварительного нажатия на элемент listview?

Как это выглядит

Также вот страница для справки:
Просмотр списка с элементами списка покупок

Я использую навигацию.PushAsync(), где я также передаю ShoppingListDetailViewModel и вводю элемент из SelectedItem

Выбранные элементы

Вот обработчик события onItemSelected в ListView для события ItemSelected:

         async void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
        {
            var item = args.SelectedItem as ShoppingList;
            if (item == null)
                return;

            await Navigation.PushAsync(new ShoppingListDetailPage(new ShoppingListDetailViewModel(item)));

            // Manually deselect item.
            ItemsListView.SelectedItem = null;
        }
  

(ItemsListView — это имя моего ListView, определенное в XAML следующим образом x:Name=»ItemsListView»)

Я пытался создать команду, которая, возможно, передавала бы объект списка покупок через параметр Command, но я запутался во всем этом, и я думаю, что для этого должно быть более простое решение, которое я просто не вижу.

XAML

Это моя страница XAML с ListView и кнопкой внутри нее:

 <ListView x:Name="ItemsListView" 
                ItemsSource="{Binding ShoppingLists}"
                RefreshCommand="{Binding LoadItemsCommand}"
                IsPullToRefreshEnabled="true"
                IsRefreshing="{Binding IsBusy, Mode=OneWay}"
                CachingStrategy="RecycleElement"
                ItemSelected="OnItemSelected">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Padding="10">
                            <Label Text="{Binding Name}" 
                                HorizontalOptions="Center"/>
                                <Label  Text="{Binding BodyHighlight}" 
                                HorizontalOptions="Center" />
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition/>
                                        <ColumnDefinition/>
                                        <ColumnDefinition/>
                                    </Grid.ColumnDefinitions>
                                    <ImageButton Grid.Column="0"
                                                 Source="delete.png"> 
                                    </ImageButton>
                                    <ImageButton 
                                        Grid.Column="1" 
                                        Source="edit.png"
                                        Clicked="EditListButton_Clicked">
                                     </ImageButton>
                                    <ImageButton 
                                        Grid.Column="2" 
                                        Source="send.png" >
                                    </ImageButton>
                                </Grid>
                            </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
  

Ответ №1:

присвоите значение текущего элемента в списке параметру CommandParameter кнопки

 <ImageButton Grid.Column="1" Source="edit.png" 
  Clicked="EditListButton_Clicked" CommandParameter="{Binding .}" />
  

затем в вашем обработчике

 public void EditListButton_Clicked(object sender, EventArgs args) 
{
  ImageButton btn = (ImageButton)sender;

  var item = (ShoppingList)btn.CommandParameter;

  if (item == null) return;

  await Navigation.PushAsync(new ShoppingListDetailPage(new ShoppingListDetailViewModel(item)));

}
  

Ответ №2:

Как я могу получить значение щелчка элемента listview изнутри кнопки, без предварительного нажатия на элемент listview?

Решение первое:

Код Xaml без изменений, и EditListButton_Clicked следующим образом:

 public void EditListButton_Clicked(object sender, EventArgs args) 
{
 ImageButton btn = sender as ImageButton;
 var item = btn.BindingContext as ShoppingList;
 if (item == null) return;
 await Navigation.PushAsync(new ShoppingListDetailPage(new ShoppingListDetailViewModel(item)));
}
  

Решение второе:

Сказано как jason, добавьте CommandParameter в ImageButton следующим образом:

 <ImageButton  Grid.Column="1" Source="edit.png" Clicked="EditListButton_Clicked" CommandParameter="{Binding .}>
  

Тогда в EditListButton_Clicked есть:

 public void EditListButton_Clicked(object sender, EventArgs args) 
{
  ImageButton btn = (ImageButton)sender;
  var item = (ShoppingList)btn.CommandParameter;
  if (item == null) return;
  await Navigation.PushAsync(new ShoppingListDetailPage(new ShoppingListDetailViewModel(item)));
}
  

Комментарии:

1. Большое спасибо. Хотя у меня есть еще один вопрос. Как вы узнали, что вам нужно выполнить эти два приведения (особенно для btn. Контекст привязки), чтобы получить доступ к этому элементу ListView? У меня проблема с пониманием этого.

2. @Tomasz Да, это немного помогает понять BindingContext. Если ItemSource вашего ListView привязан к спискам покупок, то каждая ячейка просмотра привязана к списку покупок ViewCell. Каждый элемент в привязке является списком покупок, поэтому на этот раз кнопка привязана к списку покупок. Когда BindingContext используется в проекте гораздо чаще, вы можете понять его роль. learn.microsoft.com/en-us/xamarin/xamarin-forms/xaml /…