以编程方式在Xamarin.Forms中点击按钮

5

我有一个Xamarin表单上的两个按钮,

scannerButton和checkOrderButton

scannerButton打开扫描器页面,扫描QR码并将其填入订单输入字段中

checkOrderButton读取订单输入字段中的内容,并进行验证处理,然后发送到服务器进行验证

我想要的是 - 在scannerButton.Click扫描文本后从中调用checkOrderButton.Click

代码:

private async void scanCameraButton_Clicked(object sender, EventArgs e)
{
    var options = new ZXing.Mobile.MobileBarcodeScanningOptions();
    options.PossibleFormats = new List<ZXing.BarcodeFormat>() {
        ZXing.BarcodeFormat.QR_CODE,ZXing.BarcodeFormat.EAN_8, ZXing.BarcodeFormat.EAN_13
    };

    var scanPage = new ZXingScannerPage(options);
    scanPage.OnScanResult += (result) =>
    {
        //stop scan
        scanPage.IsScanning = false;

        Device.BeginInvokeOnMainThread(() =>
        {
            //pop the page and get the result
            Navigation.PopAsync();
            orderNoEntry.Text = result.Text;
        });

            //invoke checkOrderButton.Click here

    };

如何最好地实现这一点?

其中一个替代方案是将checkOrderButton.Click处理程序中的所有功能都转储到一个函数中,然后从两个按钮点击中调用该函数,但我想学习如何通过编程方式调用单击事件。


1
在按钮上执行“PerformClick”操作?虽然最好的设计是不要通过编程方式单击按钮,而是直接调用方法。 - Sami Kuhmonen
1
不幸的是,Xamarin.Forms的Button类缺少RaiseEvent或PerformClick功能 - 设计上已经注意到了 - 我在互联网上找不到如何使用Xamarin.Forms进行点击操作的方法,所以我在这里发布了这个问题。 - Danish
4个回答

5

我为此编写了一个扩展方法。这不仅适用于Xamarin-Forms项目,也适用于WPF项目。

using System;
using System.Reflection;
using System.Windows;
using System.Windows.Input;
#if !NETSTANDARD
using System.Windows.Controls;
#else
using Xamarin.Forms;
#endif

public static class ButtonExtensions
{
    public static void PerformClick(this Button sourceButton)
    {
        // Check parameters
        if (sourceButton == null)
            throw new ArgumentNullException(nameof(sourceButton));

        // 1.) Raise the Click-event
#if !NETSTANDARD
        sourceButton.RaiseEvent(new RoutedEventArgs(System.Windows.Controls.Primitives.ButtonBase.ClickEvent));
#else
        sourceButton.RaiseEventViaReflection(nameof(sourceButton.Clicked), EventArgs.Empty);
#endif

        // 2.) Execute the command, if bound and can be executed
        ICommand boundCommand = sourceButton.Command;
        if (boundCommand != null)
        {
            object parameter = sourceButton.CommandParameter;
            if (boundCommand.CanExecute(parameter) == true)
                boundCommand.Execute(parameter);
        }
    }

#if NETSTD
    private static void RaiseEventViaReflection<TEventArgs>(this object source, string eventName, TEventArgs eventArgs) where TEventArgs : EventArgs
    {
        var eventDelegate = (MulticastDelegate)source.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(source);
        if (eventDelegate == null)
            return;
        foreach (var handler in eventDelegate.GetInvocationList())
        {
#if !(NETSTANDARD1_6 || NETSTANDARD1_5 || NETSTANDARD1_4 || NETSTANDARD1_3 || NETSTANDARD1_2 || NETSTANDARD1_1 || NETSTANDARD1_0)
            handler.Method?.Invoke(handler.Target, new object[] { source, eventArgs });
#else
            handler.GetMethodInfo()?.Invoke(handler.Target, new object[] { source, eventArgs });
#endif
        }
    }
#endif
}

4
我会做的是创建一个ViewModel,其中包含一个命令,该命令在按下按钮时执行任何逻辑。然后将按钮的Command属性绑定到ViewModel中的命令属性。此时,您将拥有一个可以像调用“Button.Click()”一样以编程方式执行的命令。

3
实际上,您需要传递两个参数,所以不只是应该是Button_Click(),而是应该这样调用:Button_Click(null, null),因为它需要sender和e作为两个必需参数,请看方法定义:Button_Click(object sender, EventArgs e){..}

0
正如Sami已经提到的那样,我建议将checkOrderButton.Click的功能提取到一个单独的方法中,这样你就可以从checkOrderButton.ClickscannerButton.Click调用该方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接