如何从基类中捕获被点击的项目(位于模板中)的事件?
Posted
技术标签:
【中文标题】如何从基类中捕获被点击的项目(位于模板中)的事件?【英文标题】:How can i capture the event of a tapped item (located in a template) from the base class? 【发布时间】:2017-03-24 10:49:37 【问题描述】:我有一个基础网格
<Grid Grid.Row="1" Grid.Column="1" x:Name="GridName">
<StackLayout Orientation="Vertical">
<art:GridOptionsView ItemsSource="Binding Items" >
<art:GridOptionsView.ItemTemplate>
<DataTemplate>
<uikit:DashboardItemTemplate />
</DataTemplate>
</art:GridOptionsView.ItemTemplate>
</art:GridOptionsView>
</StackLayout>
</Grid>
它使用以下 DashboardItemTemplate
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
BackgroundColor="White">
<ContentView.Content>
<Grid Padding="0">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center" Orientation="Vertical" Spacing="10">
<Grid>
<Label Text="" Style="StaticResource FontIcon" HorizontalTextAlignment="Center" Opacity="1" FontSize="130" TextColor="Binding BackgroundColor" VerticalOptions="Center" HorizontalOptions="Center" IsVisible="Binding Source=x:Reference Root, Path=ShowiconColoredCircleBackground" />
<Label Text="Binding Icon" Style="StaticResource FontIcon" Opacity="1" TextColor="White" VerticalOptions="Center" HorizontalOptions="Center" />
</Grid>
<Label Text="Binding Name" TextColor="Binding Source=x:Reference Root, Path=TextColor" FontSize="14" HorizontalTextAlignment="Center">
</Label>
</StackLayout>
</Grid>
</ContentView.Content>
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnWidgetTapped" />
</ContentView.GestureRecognizers>
</ContentView>
如何在我的基础 xaml 类中捕获“OnWidgetTapped”事件?
【问题讨论】:
你在使用 Grial 组件吗? 【参考方案1】:我通常使用模板中的自定义可绑定属性 ParentBindingContext
来执行此操作:
public class MyTemplate : ContentPage
public static BindableProperty ParentBindingContextProperty = BindableProperty.Create(nameof(ParentBindingContext),
typeof(object), typeof(BasePageTemplate));
public object ParentBindingContext
get return GetValue(ParentBindingContextProperty);
set SetValue(ParentBindingContextProperty, value);
然后在你的页面(包含模板)中设置ParentBindingContext
:
<DataTemplate>
<template:MyTemplate ParentBindingContext="Binding BindingContext, Source=x:Reference Name=MyPageName" />
</DataTemplate>
这样您就可以在模板中访问您页面的完整BindingContext
。下面的命令示例显示了模板如何绑定到页面的BindingContext
中的命令MyCommand
:
Command="Binding ParentBindingContext.MyCommand, Source=x:Reference Name=MyTemplatePageName"
但这前提是你的页面后面有一个BindingContext
(就像一个ViewModel)。然后,此 ViewModel 包含整个页面的“全局”命令。然后模板可以访问这些命令(或只是方法),因为它们知道页面的BindingContext
。
【讨论】:
你能告诉我什么是BasePageTemplate吗?我正在通过 DataTemplateSelector 根据某些条件分配模板。根据当前模型,我有不同的模板要显示。我在哪里可以设置 ParentBindingContext?BasePageTemplate
是模板类的名称。对于上面的示例,它将是 DashboardItemTemplate
【参考方案2】:
我将答案从流程描述更改为代码。这个想法是以编程方式创建 ItemTemplate 并将带有列表(或网格)的页面传递给它的构造函数。定义一个函数 ItemTemplateTapped 并从模板中调用它。
EventOnGridPage
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonRendererDemo.EventOnGridPage">
<ListView x:Name="listView" >
</ListView>
</ContentPage>
EventOnGridPage 后面的代码
public partial class EventOnGridPage : ContentPage
public EventOnGridPage()
InitializeComponent();
listView.ItemsSource = new List<Contact>
new Contact Name = "Kirti",Status = "True",
new Contact Name = "Nilesh",Status = "False"
;
listView.ItemTemplate = new DataTemplate(loadTemplate);
private object loadTemplate()
return new ViewCell() View = new EventOnGridTemplate(this) ;
public void ItemTemplateTapped(string name)
DisplayAlert("ItemTemplateTapped", name, "OK");
EventOnGridTemplate xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonRendererDemo.EventOnGridTemplate"
BackgroundColor="Green">
<Label Text="Binding Name" x:Name="myLabel"></Label>
</ContentView>
EventOnGridTemplate 后面的代码
public partial class EventOnGridTemplate
EventOnGridPage parent;
public EventOnGridTemplate(EventOnGridPage parent)
this.parent = parent;
InitializeComponent();
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += TapGestureRecognizer_Tapped;
myLabel.GestureRecognizers.Add(tapGestureRecognizer);
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
parent.ItemTemplateTapped(myLabel.Text);
【讨论】:
我必须承认我印象非常深刻,我希望我能跟随这背后的整个流程 我会用网格做一些代码,但不能完全重现 Grial。你能接受吗? 确保不会有问题 Sorry :-) 常规网格没有项目源且不可模板化,因此我的代码将基于 ListView 但思路相同 如果这一切都太复杂了,只需使用 Messenger :-) 在页面中订阅并从模板中触发。虽然有些人不喜欢使用 Messenger 并尽量避免使用它【参考方案3】:如果您已经在 XAML 代码中定义了点击手势绑定,则无需添加 TapGestureRecognizer,只需将您的方法签名为事件侦听器方法即可:
您的 XAML:
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnWidgetTapped" />
</ContentView.GestureRecognizers>
关于后面的 C# 代码:
public void OnWidgetTapped(object sender, EventArgs args)
// do stuff here
【讨论】:
我实际上想在基本网格中引发 OnWidgetTapped 事件,而不是在模板本身内。我怎样才能做到这一点?像事件 += 新事件,进入网格视图【参考方案4】:你只需要实现你的OnWidgetTapped
方法:
void OnWidgetTapped(object sender, System.EventArgs e)
// Do stuff here
【讨论】:
我实际上想在基本网格中引发 OnWidgetTapped 事件,而不是在模板本身内。我怎样才能做到这一点?像事件 += 新事件,进入网格视图【参考方案5】:另一种解决方案。如果您按照建议实施 OnWidgetTapped,您可以使用 sender.Parent.Parent... 直到您到达您想要的对象 - 网格或页面。将其转换为例如 EventOnGridPage,然后调用该对象的函数。
【讨论】:
以上是关于如何从基类中捕获被点击的项目(位于模板中)的事件?的主要内容,如果未能解决你的问题,请参考以下文章