#Xamarin.Forms+Prism.FormsでViewModelからViewのメソッド(WebView.EvaluateJavaScriptAsync)を呼び出す
WebViewのEvaluateJavaScriptAsyncを使用する際、VM→Vメソッド呼び出しを実装したので覚え書き。
WebViewにはローカルのHTMLファイルを設定している。
WPFなら以下サンプルソースのBindingContextをDataContextに変更する。
##実装
<?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:prism="http://prismlibrary.com"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="App.Views.ViewPage">
<ContentPage.Content>
<WebView x:Name="webView" Source="{Binding Url}" />
</ContentPage.Content>
</ContentPage>
- 「x:Name="webView"」で、View.csから参照できるように。
- 「Source="{Binding Url}"」で、UrlはViewModel.csで設定。
namespace App.Views
{
public partial class ViewPage : ContentPage
{
public ViewPage()
{
InitializeComponent();
var vm = (ViewPageViewModel)BindingContext;
vm.InvokeJsEvent += JsAsync;
}
}
async void JsAsync(string num)
{
var js = $"factorial(num)";
var result = await webView.EvaluateJavaScriptAsync(js);
}
}
- 「vm.InvokeJsEvent += JsAsync」で、ViewModelの当該イベントにViewのメソッドを登録。
namespace App.ViewModels
{
public class ViewModel : TabItemViewModelBase
{
private string _url;
private IBaseUrl _baseUrl;
public delegate void InvokeJsAction(string data);
public event InvokeJsAction InvokeJsEvent;
public ViewModel(IBaseUrl baseUrl)
{
_baseUrl = baseUrl;
}
}
public override void Initialize(INavigationParameters parameters)
{
Url = $"{_baseUrl.Get()}index.html";
}
public override void RaiseIsActiveChanged()
{
if (IsActive)
{
InvokeJsEvent?Invoke("100");
}
}
}
- 「IBaseUrl」には、デバイス別ローカルHTMLファイルのBaseUrlを格納している。
- 「InvokeJsEvent?Invoke("100");」で、イベント呼び出し→Viewのメソッド呼び出し→JSのメソッド呼び出し。
※RaiseIsActiveChangedは、TabbedPageでTabがActiveになった際に呼ばれる。
普通のContentPageなら、OnNavigatedTo()などで呼び出せば良さげ。
Initialize()などで呼び出すと、htmlが読み込まれる前にJS呼び出しを行おうとし、
NullReferenceExceptionが発生することがある様子(詳細は未調査)。
##参考
https://stackoverflow.com/questions/8658499/calling-a-method-in-views-codebehind-from-viewmodel
↑ネタ元
https://docs.microsoft.com/ja-jp/xamarin/xamarin-forms/user-interface/webview?tabs=windows
IBaseUrl(ローカルのHTMLファイル読み込み)の実装は公式ドキュメント参照。
https://stackoverflow.com/questions/58922622/how-to-trigger-onnavigatedto-on-the-second-third-tab-in-tabbedpage-using-prism
TabItemViewModelBaseのRaiseIsActiveChanged()については、↑参照。