gpt4 book ai didi

c# - Xamarin Android - 如何将事件从 MainActivity 传递到表单页面上的 ViewModel?

转载 作者:太空宇宙 更新时间:2023-11-03 20:58:26 24 4
gpt4 key购买 nike

我有一个 Xamarin Forms 应用程序,我想在上面读取 NFC 标签。我制作了一个名为 INFC 的接口(interface)来读取标签。

/// <summary>
/// This interface defines NFC relating functions that are cross platform.
/// </summary>
public interface INFC
{
/// <summary>
/// Inits the object.
/// </summary>
void Init();

/// <summary>
/// Starts the process for scanning for the included platform.
/// </summary>
/// <param name="tagInformation">Optional related tag information that you may need for the scan.</param>
void StartNFCScan(object tagInformation = null);

/// <summary>
/// Called when the tag is finished scanning and we have the content.
/// </summary>
event EventHandler<String> TagScanned;
}

我创建了以下 Android 特定实现。

[assembly: Dependency(typeof(INFCImplementation))]
namespace Test.Droid.Models
{
/// <summary>
/// The android implementation of the NFC platform.
/// </summary>
public class INFCImplementation : INFC
{
public event EventHandler<String> TagScanned;
public static NfcAdapter adapter { get; set; }

/// <summary>
/// Called to init the object.
/// </summary>
public void Init()
{
//Set the adapter.
adapter = NfcAdapter.GetDefaultAdapter(Forms.Context);
}

/// <summary>
/// Starts the process for scanning for the included platform.
/// </summary>
/// <param name="tagInformation">Optional related tag information that you may need for the scan.</param>
public void StartNFCScan(object tagInformation = null)
{
//Create a variable to hold the tag content.
String tagContent = null;

try
{
//Process the NDEF tag and get the content as a String.
tagContent = "http://stackoverflow.com";
}
catch (Exception e)
{
}

//Raise the tag content with the scanned event.
TagScanned?.Invoke(this, tagContent);
}
}

我的主要 Activity 如下。

/// <summary>
/// The main activity for the app.
/// </summary>
[Activity(Label = "Test", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
INFCImplementation nfcImplementation;

protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;

base.OnCreate(bundle);

//Enable experimental fast renderers.
Forms.SetFlags("FastRenderers_Experimental");

Forms.Init(this, bundle);

//Load up the zxing framework.
ZXing.Net.Mobile.Forms.Android.Platform.Init();

//Load up the user dialogs plugin.
UserDialogs.Init(() => (Activity)Forms.Context);

//Init the tinted image renderer.
TintedImageRenderer.Init();

//Store our NFC interface class.
nfcImplementation = DependencyService.Get<INFCImplementation>() as INFCImplementation;

//Init our NFC interface.
nfcImplementation.Init();

LoadApplication(new App());
}

protected override void OnResume()
{
//Call the base method.
base.OnResume();

//Create the intent for NFC reading.
Intent intent = new Intent(this, GetType()).AddFlags(ActivityFlags.SingleTop);

//Start a dispatch on our NFC adapter.
INFCImplementation.adapter?.EnableForegroundDispatch
(
this,
PendingIntent.GetActivity(this, 0, intent, 0),
new[] { new IntentFilter(NfcAdapter.ActionTechDiscovered) },
new String[][]
{
new string[]
{
"android.nfc.tech.Ndef"
},
new string[] {
"android.nfc.tech.MifareClassic"
},
}
);
}

protected override void OnPause()
{
//Call the base method.
base.OnPause();

//Stop the dispatch on our NFC adapter.
INFCImplementation.adapter?.DisableForegroundDispatch(this);
}

protected override void OnNewIntent(Intent intent)
{
//Call the base method.
base.OnNewIntent(intent);

//Check if this is the NFC intent.
if (intent != null && (NfcAdapter.ActionNdefDiscovered.Equals(intent.Action) || NfcAdapter.ActionTechDiscovered.Equals(intent.Action) || NfcAdapter.ActionTagDiscovered.Equals(intent.Action)))
{
var test = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
nfcImplementation.StartNFCScan(test);
}
}

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
//Call the base method.
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

//Check with the permissions plugin.
PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);

//Check with the zxing plugin.
ZXing.Net.Mobile.Android.PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

在作为主页绑定(bind)上下文的主页 View 模型中,我在构造函数中添加了以下内容。

    /// <summary>
/// Constructs the scanner view model with the scanner view we want to use.
/// </summary>
public ScannerPageViewModel()
{
//Subscribe to the tag scanned event.
CrossNFC.Current.TagScanned += ProcessNFCScanResult;
}

private void ProcessNFCScanResult(object sender, string e)
{
SetLabel(e);
}

好的,这个问题。我相信这应该使 OnNewIntent 函数将调用界面上的开始 NFC 扫描,然后调用将一直飞到 View 模型并允许我处理的事件内容。我这样做是因为我只想在应用程序处于前台时扫描应用程序中一页上的 NFC 标签。每次调用调用时,TagScanned 事件都是空的。

在周围放置断点我发现扫描标签时出现以下情况:

调用 MainActivity OnPause -> 调用扫描仪页面 OnDisappearing -> 调用 OnNewIntent 并调用空事件 -> 调用 MainActivity OnResume -> 调用扫描仪页面 OnAppearing

我认为 OnDisappearing 调用使事件无法处理。我的很多代码都基于 NFCForms Github 项目 ( https://github.com/poz1/NFCForms ),当下载示例项目并运行它时,它不会触发 OnDisappearing 和 OnAppearing。它只是调用 OnPause、OnNewIntent 和 OnResume,然后事件到达他的页面。

为什么我的页面被卸载并且事件没有被调用?如果我做错了什么,我如何在扫描标签时通知特定页面的 ViewModel?我认为这要么是我发出 NFC Intent 请求的方式的问题,要么是与 NFC 无关的问题,在 NFC 中,由于示例 NFCForms 应用程序在同一部手机上正常工作,我处理 View 事件时出错。

编辑

我用相同的基本代码创建了一个全新的项目,它以我认为应该的方式工作。现在我想弄清楚为什么在页面上调用 OnAppearing 和 OnDisappearing。

编辑2

我发现如果页面包含在导航页面中,则会调用 OnAppearing 和 OnDisappearing。这就是为什么作为单一 View 的新项目没有调用它,而当我添加导航页面时它确实调用了它。

但是,即使将我的项目更改为单个页面,我正在处理的旧项目的事件仍然为空,而新测试项目的事件为有效。

所以我在想,不知何故我没有正确地处理事件?

最佳答案

这对您的情况有用吗?

// In ScannerPage
protected override void OnAppearing ()
{
base.OnAppearing ();
MessagingCenter.Subscribe<string>(this, "eventName", (label) => {
// do something whenever the message is sent
Device.BeginInvokeOnMainThread (() => {
MyScannerPageViewModel.SetLabel(label);
});
});
}

protected override void OnDisappearing ()
{
base.OnDisappearing ();
MessagingCenter.Unsubscribe<string> (this, "eventName");
}

然后在 MainActivity 中选择您要放置此行的位置

Xamarin.Forms.MessagingCenter.Send("LabelName","eventName");

编辑:稍微更改了代码

关于c# - Xamarin Android - 如何将事件从 MainActivity 传递到表单页面上的 ViewModel?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48047444/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com