How can i capture the event of a tapped item (located in a template) from the base class?

∥☆過路亽.° 提交于 2019-12-07 12:03:01

问题


I have a base grid

<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>

which uses the following 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>

How can i capture the "OnWidgetTapped" event on my base xaml class?


回答1:


I do this usually with a custom bindable property ParentBindingContext in my template:

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); }
    }
}

And then in your page (which contains the template) just set the ParentBindingContext:

<DataTemplate>
    <template:MyTemplate ParentBindingContext="{Binding BindingContext, Source={x:Reference Name=MyPageName}}" />
</DataTemplate>

With that you can access the full BindingContext of your page in your template. The following example of a command shows how the template can bind to a command MyCommand, which is in the BindingContext of the page:

Command="{Binding ParentBindingContext.MyCommand, Source={x:Reference Name=MyTemplatePageName}}"

But this presupposes that your page has a BindingContext behind (like a ViewModel). This ViewModel then contains the "global" commands for the whole page. These commands (or just methods) can then be accessed by the template, because they know about the BindingContext of the page.




回答2:


I changed an answer from flow description to the code. The idea is to create ItemTemplate programatically and pass to its constructor the page with list (or grid). Define a function ItemTemplateTapped and call it from template.

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 code behind

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 code behind

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);

    }
}



回答3:


If you already defined the tap gesture binding in the XAML code, you don't need to add the TapGestureRecognizer, simply sign your method to an event listener method:

Your XAML:

<ContentView.GestureRecognizers>
    <TapGestureRecognizer Tapped="OnWidgetTapped" />
</ContentView.GestureRecognizers>

On C# code behind:

public void OnWidgetTapped(object sender, EventArgs args)
{
// do stuff here
}



回答4:


You just need to implement your OnWidgetTapped method:

void OnWidgetTapped(object sender, System.EventArgs e)
{
    // Do stuff here
}



回答5:


Another solution. If you implemented OnWidgetTapped as was suggested you can use sender.Parent.Parent... till you get to the object you want - grid or page. Cast it to for example EventOnGridPage and then call the function of that object.



来源:https://stackoverflow.com/questions/40527092/how-can-i-capture-the-event-of-a-tapped-item-located-in-a-template-from-the-ba

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!