Привязка команд TapGestureRecognizer Xamarin Forms ControlTemplate - PullRequest
1 голос
/ 21 марта 2019

У меня есть ControlTemplate, который я собираюсь использовать для предоставления основных функций большинству всех страниц моего приложения.

Хорошие ссылки на идею:

Я столкнулся с чем-то странным при попытке связать TapGestureRecognizer с ICommand в контексте связывания. Мне удалось связать свойство ICommand в моем представлении просто отлично, используя кнопку, но совсем не используя TapGestureRecognizer.

У меня есть изображение стрелки назад, которое я хотел бы использовать для навигации назад на большинстве всех страниц, и использование изображения с TapGestureRecognizer кажется естественным, если я могу заставить команду привязываться к моему представлению (как это происходит при использовании кнопка).

Кнопка над рамкой ниже была экспериментом, чтобы доказать, что команда закодирована нормально. Странно, но кнопка прекрасно работает с точно такой же привязкой для своей команды, в то время как TGR ничего не делает.

Часть моего ControlTemplate XAML:

<Button Grid.Row="1" HorizontalOptions="Start" VerticalOptions="Start" IsVisible="{TemplateBinding BindingContext.ShowBack}" Text ="Back" Command="{TemplateBinding BindingContext.BackNavCommand}" Margin="90,0,0,0"/>

<!-- LATE EDIT - The TGR on this Frame is doomed not to work.  The whole frame should be defined BELOW the Content Presenter.  Read on below for why. -->
<Frame Grid.Row="1" HorizontalOptions="Start" VerticalOptions="Start" IsVisible="{TemplateBinding BindingContext.ShowBack}" BackgroundColor="Cyan" BorderColor="Transparent" HasShadow="False" HeightRequest="50" WidthRequest="50">
<Frame.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform ="iOS" Value="5,25,0,0"/>
<On Platform ="Android" Value="5,5,0,0"/>
<On Platform ="UWP" Value="5,5,0,0"/>
</OnPlatform>
</Frame.Padding>
<Frame.GestureRecognizers>
<TapGestureRecognizer x:Name="backTapped" Command="{TemplateBinding BindingContext.BackNavCommand}" />
</Frame.GestureRecognizers>
<Image x:Name="backImage"  Source="back.png" Aspect="AspectFit" HeightRequest="20" WidthRequest="30" VerticalOptions="Center" HorizontalOptions="Center" InputTransparent="True"/>
</Frame>
<ContentPresenter Grid.Row="1"/>

Я установил фоновый цвет рамки, содержащей изображение голубого цвета, чтобы убедиться, что моя область касания обнаруживается. Он явно есть, но нажатие на него никогда не активирует TGR и соответствующую команду, которую я установил для его запуска.

Примечание. Мое содержимое для заполнения в ContentPresenter имеет прозрачный фон, на котором отображается фоновое изображение главной страницы. Это ключ к этому сценарию, так как сложно сказать, что перед чем.

1 Ответ

0 голосов
/ 21 марта 2019

Aha! Как это часто бывает, когда вы намереваетесь четко определить свою проблему, у вас возникают идеи, как ее решить.

Я сталкивался с этим раньше, но забыл: Z ЗАКАЗАТЬ!

Я знал, что мой элемент управления ControlTemplate будет разделять пространство Content Presenter, потому что он все помещается в Grid.Row 1. Чтобы заставить этот TapGestureRecognizer работать должным образом, мне нужно было определить его в моем ControlTemplate XAML ниже ContentPresenter. Таким образом, элемент управления все еще оказывается в том же месте, НО он оказывается в ТОПе содержимого шаблона, потому что он был определен позже (можно сказать, выше в визуальном стеке).

Точно так же работает TGR. Кажется, у кнопки меньше манер. Кнопка работала нормально, как показано здесь, над ContentPresenter.

Примечание: я нашел этот отличный способ поместить очень многократно используемый ActivityIndicator в мой ControlTemplate. Опять же, он должен быть ниже ContentPreseneter, иначе счетчик будет отображаться на заднем плане, между полями ввода и т. Д.

Подсказка. Возможно, вам не нужно делить пространство с шаблонными элементами управления, но если вы делаете это и хотите, чтобы шаблонные элементы управления были доступны и находились впереди, то определите под ними ContentPresenter в своем шаблоне!

Примечание к TemplateBinding.

Во многих местах отмечалось, что когда вы связываете элемент управления ControlTemplate, вы используете этот синтаксис (например, привязка IsVisible здесь):

IsVisible="{TemplateBinding BindingContext.ShowBack}"

Точно то, на что здесь ссылается BindingContext, зависит .... Если ваша страница устанавливает BindingContext в свой конструктор как "this", тогда шаблон будет искать привязываемое свойство 'ShowBack' в представлении, что шаблон оборачивается содержимым .
Однако если вы установите BindingContext для представления, которое шаблон оборачивает содержимым, в качестве объекта ViewModel, то BindingContext будет искать там связываемое свойство с именем ShowBack. Узнал об этом из экспериментов и подумал, что поделюсь.

...