Xamarin Forms TapGestureRecognizer не выдает команду

#c# #xamarin #xamarin.forms #mvvm #xamarin.android

Вопрос:

Итак, у меня есть приложение xamarin forms, которое в настоящее время реализовано только для Android. Я пытаюсь реализовать событие tap. При нажатии, хотя это никогда не попадает в команду в ViewModel. Я не уверен, что у меня что-то не так с моим кодом, или я просто неправильно его реализую.

Код модели просмотра:

     private RelayCommand<object> _OnClickableLabel;

    public RelayCommand<object> OnClickableLabel
    {
        get { return _OnClickableLabel ?? (_OnClickableLabel = new RelayCommand<object>((currentObject) => Test(currentObject))); }
    }

    private void Test(object currentObject)
    {
        Application.Current.MainPage.DisplayAlert("Alert", "were going down cap", "OK");
    }
 

Страница Xaml:

   <ListView Grid.Row="1" ItemsSource="{Binding Notifications}" RowHeight="100">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Vertical"  BackgroundColor="{Binding BackgroundColor}">
                    <StackLayout.GestureRecognizers>
                        <TapGestureRecognizer Command="{Binding OnClickableLabel }" />
                    </StackLayout.GestureRecognizers>
                    <Label FontSize="Large" Text="{Binding Title}"></Label>
                    <Label FontSize="Small" Text="{Binding Text}"></Label>
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
 

Я протестировал его с помощью метода в cs-коде страницы, и это работает нормально, но его необходимо реализовать в ViewModel, потому что это влияет на эти данные.

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

1. ваша команда находится на базовой виртуальной машине, но BindingContext каждая строка в ListView ней является отдельным Notification объектом, а не всей виртуальной машиной. Вы можете обойти это, используя относительную привязку

2. Не знал об этом, довольно новичок в Xamarin. Я предполагаю, что использую версию RelativeSource типа AncestorType? Где мне выяснить, какой тип должен быть в AncestorType? Размещение модели представления там, похоже, не работает.

3. Другой обходной путь может заключаться в том, чтобы дать вашей странице имя , например x:Name="this" , затем указать источник в привязке, что-то вроде: Command="{Binding OnClickableLabel, Source={x:Reference this} }"

Ответ №1:

Из вашего описания следует, что вы хотите добавить распознаватель жестов касания в ListView и хотите передать данные текущей строки ListView в событие TapGestureRecognizer, я прав?

Если да, то, по мнению Джейсона, вам нужно взглянуть на Xamarin.Формирует относительные привязки во-первых,назовите ListView как listview1, затем посмотрите следующий код:

 <ListView
            x:Name="listview1"
            Grid.Row="1"
            ItemsSource="{Binding Notifications}"
            RowHeight="100">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout BackgroundColor="{Binding BackgroundColor}" Orientation="Vertical">
                            <StackLayout.GestureRecognizers>
                                <TapGestureRecognizer Command="{Binding BindingContext.OnClickableLabel, Source={x:Reference listview1}}" CommandParameter="{Binding .}" />
                            </StackLayout.GestureRecognizers>
                            <Label FontSize="Large" Text="{Binding Title}" />
                            <Label FontSize="Small" Text="{Binding Text}" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

public partial class Page16 : ContentPage
{
    public ObservableCollection<Notclass> Notifications { get; set; }
    public ICommand OnClickableLabel { get; set; }
    public Page16()
    {
        InitializeComponent();
        Notifications = new ObservableCollection<Notclass>()
        {
            new Notclass(){Title="title 1",Text="notification 1"},
            new Notclass(){Title="title 2",Text="notification 2"},
            new Notclass(){Title="title 3",Text="notification 3"},
            new Notclass(){Title="title 4",Text="notification 4"},
            new Notclass(){Title="title 5",Text="notification 5"}

        };
        OnClickableLabel = new Command(n=> {
            var vm = (Notclass)n;
            Application.Current.MainPage.DisplayAlert("Alert",vm.Title , "OK"); 
        });

        this.BindingContext = this;
    }
}

public class Notclass
{
    public string Title { get; set; }
    public string Text { get; set; }
    public Color BackgroundColor { get; set; } = Color.White;
}