Alan2
Alan2

Reputation: 24572

How can I pass a Tapped event into a XAML template?

I code that I use often in my application so I created this template. With a lot of help from the user gannaway the code I have so far is this:

<?xml version="1.0" encoding="utf-8" ?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          xmlns:local="clr-namespace:Japanese;assembly=Japanese"
          x:Class="Japanese.SwitchViewCellTemplate"
          x:Name="this">
   <Grid VerticalOptions="CenterAndExpand" Padding="20,0" >
      <local:StyledLabel Text="{Binding Text, Source={x:Reference this}}" HorizontalOptions="StartAndExpand" />
      <local:StyledLabel IsVisible="{Binding IsVisible, Source={x:Reference this}}" TextColor="Gray" HorizontalOptions="End" Text="✓" />
   </Grid>
</ViewCell>

Here's the code behind:

using System;
using System.Collections.Generic;
using Xamarin.Forms;

namespace Japanese
{
    public partial class SwitchViewCellTemplate : ViewCell
    {
        public event EventHandler SelectAction;

        public SwitchViewCellTemplate()
        {
            InitializeComponent();
        }

        public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(SwitchViewCellTemplate));
        public static readonly BindableProperty IsVisibleProperty = BindableProperty.Create(nameof(IsVisible), typeof(bool), typeof(SwitchViewCellTemplate));

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
        public bool IsVisible
        {
            get { return (bool)GetValue(IsVisibleProperty); }
            set { SetValue(IsVisibleProperty, value); }
        }

        protected override void OnTapped()
        {
            base.OnTapped();
            this.SelectAction?.Invoke(this, new EventArgs());
        }
    }
}

and the way I would like to use it:

<template:SwitchViewCellTemplate Text="{Binding [1].Name}" 
    IsVisible="{Binding [1].IsSelected}" 
    SelectAction="selectValue" />

Here is the method used to handle toggled:

    void Handle_SelectAction(object sender, System.EventArgs e)
    {
        var viewCell = sender as ViewCell;
        if (viewCell == null)
            return;
    }

Where selectValue is a function in the CS code behind of the pages where I use the template.

The code gives an error:

 The type initializer for 'Japanese.SwitchViewCellTemplate' threw an exception.

Can anyone give me advice on what might be wrong that is causing this error.

Upvotes: 0

Views: 108

Answers (1)

gannaway
gannaway

Reputation: 1882

To solve, an event can be added to the template.

XAML Template

<?xml version="1.0" encoding="utf-8" ?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          xmlns:local="clr-namespace:Japanese;assembly=Japanese"
          x:Class="Japanese.SwitchViewCellTemplate"
          x:Name="this">
   <Grid VerticalOptions="CenterAndExpand" Padding="20,0" >
      <local:StyledLabel Text="{Binding Text, Source={x:Reference this}}" HorizontalOptions="StartAndExpand" />
      <local:StyledLabel IsVisible="{Binding IsVisible, Source={x:Reference this}}" TextColor="Gray" HorizontalOptions="End" Text="✓" />
   </Grid>
</ViewCell>

Add an event to your template's code-behind:

public partial class SwitchViewCellTemplate : ViewCell
{
    public event EventHandler SelectAction;

    public SwitchViewCellTemplate()
    {
        InitializeComponent();
    }

    public static readonly BindableProperty TextProperty = 
        BindableProperty.Create(
            nameof(Text), 
            typeof(string), 
            typeof(SwitchViewCellTemplate),
            default(string));

    public static readonly BindableProperty IsVisibleProperty = 
        BindableProperty.Create(
            nameof(IsVisible), 
            typeof(bool), 
            typeof(SwitchViewCellTemplate),
            default(bool));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    public bool IsVisible
    {
        get { return (bool)GetValue(IsVisibleProperty); }
        set { SetValue(IsVisibleProperty, value); }
    }

    protected override void OnTapped()
    {
        base.OnTapped();
        this.SelectAction?.Invoke(this, new EventArgs());
    }
}

Page XAML

<template:SwitchViewCellTemplate Text="{Binding [1].Name}" 
    IsVisible="{Binding [1].IsSelected}" 
    SelectAction="Handle_SelectAction" />

Page Code-Behind

    void Handle_SelectAction(object sender, System.EventArgs e)
    {

    }

Upvotes: 2

Related Questions