Xamarin Forms 自定义控制命令未被解雇

Xamarin Forms Custom Control Command not getting fired

我正在创建一个特定于平台的自定义按钮,其文本和图像在 Android 和 iOS 中具有自定义渲染器。我的问题是,我的按钮上的 Click Command 没有被触发。

我创建了自定义 android 渲染器,强制使用自定义 android 布局。

Xamarin.Form 按钮 Class:

    public static readonly BindableProperty CommandProperty =
        BindableProperty.Create("Command", typeof(ICommand), typeof(ImageButton), null,
            BindingMode.TwoWay, propertyChanged: OnCommandChanged);
    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public EventHandler Clicked;

    private static void OnCommandChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var control = (ImageButton)bindable;

        // this gesture recognizer will inovke the command event whereever it is used
        control.GestureRecognizers.Add(new TapGestureRecognizer
        {
            Command = (Command)newValue,
            CommandParameter = control.CommandParams
        });
    }        
    
    public ImageButton()
    {
        this.GestureRecognizers.Add(new TapGestureRecognizer
        {
            Command = new Command(() =>
            {
                Clicked?.Invoke(this, EventArgs.Empty);

                if (Command != null)
                {
                    if (Command.CanExecute(CommandParams))
                        Command.Execute(CommandParams);
                }
            })
        });
    }

Android 渲染器:

[assembly: ExportRenderer(typeof(ImageButton), typeof(ImageButtonRenderer))]
    namespace Droid.Extensions.Renderers
    {
        public class ImageButtonRenderer : ViewRenderer<ImageButton, Android.Views.View>
        {
    private readonly Context context;
    private TextView buttonText;
    private ImageView buttonIcon;

    public ImageButtonRenderer(Context context) : base(context)
    {
        this.context = context;
    }

    protected override void OnElementChanged(ElementChangedEventArgs<Controls.ImageButton> e)
    {
        base.OnElementChanged(e);

        if (Control == null)
        {
            var inflater = context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
            var rootLayout = inflater.Inflate(Resource.Layout.ImageButton, null, false);

            buttonText = (TextView) rootLayout.FindViewById(Resource.Id.image_button_text);
            buttonText.Text = Element.Text;
            buttonIcon = (ImageView)rootLayout.FindViewById(Resource.Id.image_button_icon);
            
                    
            SetNativeControl(rootLayout);
            rootLayout.Click += (s, a) => Element.Command?.Execute(a);
        }
    }

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

消耗控制:

<control:ImageButton
                    Source="ai_tab_menu"
                    Margin="10"
                    Command="{Binding MyCommand}"
                    Text="This is a test!">

查看模型:

    public class TabHomeMenuViewModel : INotifyPropertyChanged
{
    string message = string.Empty;
    public string Message
    {
        get { return message; }
        set
        {
            message = value;
            PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs("Message"));
        }
    }

    public Command MyCommand { get; private set; }

    public TabHomeMenuViewModel()
    {
        // configure the TapCommand with a method

        Message = "Waiting";
        MyCommand = new Command(UpdateVersion);
    }

    private void UpdateVersion()
    {
        Message += "Clicked ";
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

我也有同样的问题。我试图通过 BehaviorsPack 绑定一个命令。它与原始元素完美搭配。自定义控件不起作用。我在 xamarin formum 中发布了一个主题,但没有得到答案:https://forums.xamarin.com/discussion/182224/entry-works-with-eventtocommandbehavior-custom-renderner-does-not

我找到了我的代码的问题。我正在将点击事件分配给不可点击的根布局。所以我将点击分配给内部布局。

SetNativeControl(rootLayout);
rootLayout.FindViewById(Resource.Id.image_button).Click += (s, a) =>
{
   Element.RaiseCommand();
};

此外,我们必须将事件从 Native Control 冒泡到 Forms。

public void RaiseCommand()
{
    Clicked?.Invoke(this, EventArgs.Empty);

    if (Command != null && Command.CanExecute(CommandParams))
        Command.Execute(CommandParams);
}