Добавление событий

Последнее обновление: 13.01.2021

В прошлой теме в элемент HeaderView были добавлены свойства. Теперь добавим также и события. В частности, событие нажатия.

Для вызова события нам необязательно писать какой-то код в самом элементе. В нем мы можем только определить нужные события, а затем их генерировать в рендерере.

Так, определим в классе HeaderView событие TappedOrClickEvent:

using System;
using Xamarin.Forms;

namespace HelloApp
{
    public class HeaderView : View
    {
        public event EventHandler TappedOrClickEvent;
        public void FireClick(EventArgs e)
        {
            if (this.TappedOrClickEvent != null)
                this.TappedOrClickEvent(this, e);
        }

        public static readonly BindableProperty TextProperty = 
            BindableProperty.Create("Text", typeof(string), typeof(HeaderView), string.Empty);
        public string Text
        {
            set
            {
                SetValue(TextProperty, value);
            }
            get
            {
                return (string)GetValue(TextProperty);
            }
        }

        public static readonly BindableProperty TextColorProperty =
            BindableProperty.Create("TextColor", typeof(Color), typeof(HeaderView), Color.Default);
        public Color TextColor
        {
            set
            {
                SetValue(TextColorProperty, value);
            }
            get
            {
                return (Color)GetValue(TextColorProperty);
            }
        } 
    }
}

На странице используем это событие:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:HelloApp;assembly=HelloApp"
             x:Class="HelloApp.MainPage">
  <StackLayout>
    <local:HeaderView x:Name="headerView1" Text="Simple HeaderView" 
					TappedOrClickEvent="ChangeText"></local:HeaderView>
  </StackLayout>
</ContentPage>

А в файле кода страницы пропишем обработчик:

using System;
using Xamarin.Forms;

namespace HelloApp
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            
        }
        int clicks = 0;
        private void ChangeText(object sender, EventArgs e)
        {
            HeaderView hView = sender as HeaderView;
            hView.Text = $"{++clicks} clicks";
        }
    }
}

Теперь изменим рендерер для Android:

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Util;
using Android.Widget;
using HelloApp;
using HelloApp.Droid;
using System.ComponentModel;

[assembly: ExportRenderer(typeof(HeaderView), typeof(HeaderViewRenderer))]
namespace HelloApp.Droid
{
    public class HeaderViewRenderer : ViewRenderer<HeaderView, TextView>
    {
		public HeaderViewRenderer(Context context) : base(context)
        {
        }
        protected override void OnElementChanged(ElementChangedEventArgs<HeaderView> args)
        {
            base.OnElementChanged(args); 
            if (Control == null)
            {
                // создаем и настраиваем элемент
                TextView textView = new TextView(Context);
                textView.SetTextSize(ComplexUnitType.Dip, 28);
                textView.Touch += TextView_Touch;
                // устанавливаем элемент для класса из Portable-проекта
                SetNativeControl(textView);
                // установка свойств
                if (args.NewElement != null)
                {
                    SetText();
                    SetTextColor();
                }
            }
        }

        private void TextView_Touch(object sender, TouchEventArgs e)
        {
            if (Element != null)
                Element.FireClick(System.EventArgs.Empty);
        }

        // изменения свойства
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == HeaderView.TextColorProperty.PropertyName)
            {
                SetTextColor();
            }
            else if (e.PropertyName == HeaderView.TextProperty.PropertyName)
            {
                SetText();
            }
        }
        private void SetText()
        {
            Control.Text = Element.Text;
        }
        private void SetTextColor()
        {
            Android.Graphics.Color andrColor = Android.Graphics.Color.Gray;

            if (Element.TextColor != Xamarin.Forms.Color.Default)
            {
                Xamarin.Forms.Color color = Element.TextColor;
                andrColor = Android.Graphics.Color.Argb(
                    (byte)(color.A * 255),
                    (byte)(color.R * 255),
                    (byte)(color.G * 255),
                    (byte)(color.B * 255));
            }
            Control.SetTextColor(andrColor);
        }
    }
}

Ключевым моментом для обработки события здесь является обработка события Touch нативного элемента TextView. В его обработчике по сути мы переадресуем вызовы элементу HeaderView:

Element.FireClick(System.EventArgs.Empty);

Это общая схема обработки событий, которая работает вне зависимости от события элемента: в обработчиках событий нативного элемента мы генерируем события элемента из Xamarin.Forms.

Также изменим код рендерера для iOS:

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using UIKit;
using HelloApp;
using HelloApp.iOS;
using System.ComponentModel;

[assembly: ExportRenderer(typeof(HeaderView), typeof(HeaderViewRenderer))]
namespace HelloApp.iOS
{
    public class HeaderViewRenderer : ViewRenderer<HeaderView, UILabel>
    {
        UITapGestureRecognizer tapGestureRecognizer;
        protected override void OnElementChanged(ElementChangedEventArgs<HeaderView> args)
        {
            base.OnElementChanged(args);
            if (Control == null)
            {
                UILabel uilabel = new UILabel
                {
                    Font = UIFont.SystemFontOfSize(25)
                };
                tapGestureRecognizer = new UITapGestureRecognizer(() => { OnHeaderViewTapped(); });
                uilabel.AddGestureRecognizer(tapGestureRecognizer);
				uilabel.UserInteractionEnabled = true;
                SetNativeControl(uilabel);
            }
            if (args.NewElement != null)
            {
                SetText();
                SetTextColor();
            }
        }

        private void OnHeaderViewTapped()
        {
            if(Element!=null)
            {
                Element.FireClick(System.EventArgs.Empty);
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == HeaderView.TextColorProperty.PropertyName)
            {
                SetTextColor();
            }
            else if (e.PropertyName == HeaderView.TextProperty.PropertyName)
            {
                SetText();
            }
        }
        private void SetText()
        {
            Control.Text = Element.Text;
        }
        private void SetTextColor()
        {
            UIColor iosColor = UIColor.Gray;

            if (Element.TextColor != Xamarin.Forms.Color.Default)
            {
                Xamarin.Forms.Color color = Element.TextColor;
                iosColor = UIColor.FromRGBA(
                    (byte)(color.R * 255),
                    (byte)(color.G * 255),
                    (byte)(color.B * 255),
                    (byte)(color.A * 255));
            }
            Control.TextColor = iosColor;
        }
    }
}

Здесь для обработки нажатия используется класс UITapGestureRecognizer.

И изменим код рендерера для UWP:

using Xamarin.Forms.Platform.UWP;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using HelloApp;
using HelloApp.UWP;
using System.ComponentModel;

[assembly: ExportRenderer(typeof(HeaderView), typeof(HeaderViewRenderer))]
namespace HelloApp.UWP
{
    public class HeaderViewRenderer : ViewRenderer<HeaderView, TextBlock>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<HeaderView> args)
        {
            base.OnElementChanged(args);
            if (Control == null)
            {
                TextBlock textBlock = new TextBlock
                {
                    FontSize = 28
                };
                textBlock.Tapped += TextBlock_Tapped;
                SetNativeControl(textBlock);
                if (args.NewElement != null)
                {
                    SetText();
                    SetTextColor();
                }
            }
        }

        private void TextBlock_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
        {
            if(Element!=null)
            {
                Element.FireClick(System.EventArgs.Empty);
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (e.PropertyName == HeaderView.TextColorProperty.PropertyName)
            {
                SetTextColor();
            }
            else if (e.PropertyName == HeaderView.TextProperty.PropertyName)
            {
                SetText();
            }
        }

        private void SetText()
        {
            Control.Text = Element.Text;
        }
        private void SetTextColor()
        {
            Windows.UI.Color winColor = Windows.UI.Colors.Black;
            
            if (Element.TextColor != Xamarin.Forms.Color.Default)
            {
                Xamarin.Forms.Color color = Element.TextColor;
                winColor = Windows.UI.Color.FromArgb(
                    (byte)(color.A * 255),
                    (byte)(color.R * 255),
                    (byte)(color.G * 255),
                    (byte)(color.B * 255));
            }
            Control.Foreground = new SolidColorBrush(winColor);
        }
    }
}
Events in Custom Renderer in Xamarin.Forms
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850