2016-04-01 17 views
1

WPF WebBrowserコントロールを実装するアプリケーションがあります。おそらく他のスレッドからアプリケーションから呼び出さなければならないいくつかのJS関数を含むページを読み込みます。私はMVVMのパターンに固執し、モデル内で関数の戻り値を解析するコードを保持しておきたいと思います。 WebBrowserオブジェクトでInvokeScriptメソッドを呼び出すことは、UI要素であるため、Dispatcherスレッド(したがってビュー)で実行する必要があります。ディスパッチャなしのWPF WebブラウザでJavascriptを呼び出す

私は現在、この仕事を得るための手順は、(大体擬似中)である:

- subscribe to the LoadCompleted event of the browser (view) 
- set the browser source (model -> viewmodel -> view) 
- catch the LoadCompleted event (view -> viewmodel -> model) 
- some logic (model) 
- invoke script (model -> viewmodel -> view) 
- get script result (view -> viewmodel -> model) 
- some logic (model) 

これは、(のviewmodel経由)モデルとビューの間でかなりの前後コミュニケーションにつながります。私はWPF(またはその点ではMVVM)で経験したことがないので、私はこの仕事をよりうまくやり遂げる方法があるのか​​どうか疑問に思っています(ちなみに、モデルとビューモデルとビューの間の呼び出しやイベントが少ない)。

答えて

0

私はこれがあなたの質問に対する答えではないことを知っていますが、それは将来あなたをさらに助けるかもしれません。 CefSharpというコンポーネントを見てください。これはChrome Embedded FrameworkのC#ラッパーです。それは非常にMVVMに優しいです、それはオープンソース、無料であり、それは合理的に開発するのが簡単です。私は最近、別のChromeラッパー(Awesomium)からそれに移動し、とても満足しています。

CefSharpを使用すると、ページからjs関数を呼び出すことができ、それらの呼び出しに対してasync/awaitをサポートすることもできます。

+0

素敵な提案ということ。ただし、AwasomiumまたはWPF WebBrowserのいずれかと比較して、CefSharpの実際の利点は何ですか? – Bart

+0

Awesomiumの利点は、CefSharpがオープンソースで無料であることです。 Awesomiumのサポートは非​​常に欠けています。彼らはあなたが彼らが大きくて真面目な会社だと信じて欲しいですが、真実はただの人です。コードが公開されていないので、バグを修正するために開発者が手を差し伸べています。プロジェクトは非常にゆっくりと動きます。私は彼らがまだクロム16のようなものを使っていると信じています。 –

+0

ネイティブのWPF Webブラウザコントロールに関しては、私はそれに多くの経験がないことを認めます。私たちはちょっと、最初から第三者コントロールの道を歩いていました。 しかし、いくつかのことが考えられます。たとえば、CefSharpがMVVMパターンを念頭に置いて構築されているという事実のように。ほとんどすべてがコマンドまたは依存プロパティです。 さらに、ブラウザとのやりとりは、async/awaitで完了します。これはネイティブのWPFコントロールよりもポジティブです。 –

0

MVVMの主なポイントは、異なるプラットフォームのロジック(viewmodel \ model)を再利用できるように、プラットフォーム(プラットフォーム固有の:windows \ android \ ios \ windows phone etcなど)をすべて分離することです。ですから、ViewModelからInvokeScriptを直接呼び出すことはできませんが、ディスパッチャのためではありません。ディスパッチャーを抽象化することができます(for example)。これは、ビュー・モデルで必要な場合があるためです。だから、通常のviewmodelビューで操作を実行する必要がある場合 - イベント(または単に代表者)が使用されています。

public class MyViewModel 
{ 
    public Func<string, object> InvokeScript { get; set; } 
    public Func<string, Task<object>> InvokeScriptAsync { get; set; } 

    public async void Something() { 
     var result = await InvokeScriptAsync("my script"); 
     // do something 
    } 
} 

そして、あなたのビューで:

public class MyView { 
    private void OnViewModelChanged(MyViewModel vm) { 
     vm.InvokeScript = text => Dispatcher.Invoke(() => browser.InvokeScript(text)); 
     vm.InvokeScriptAsync = text => browser.InvokeScriptAsync(text); // for example 
    } 
} 
+0

はい、私は完全に理解しています。私が達成しようとしているのは、ビューを(ビュー)モデルから分離することです。だからあなたは、ビューモデルからコミュニケーションのためにイベント(または代理人)を使用するだけでいいということですか? – Bart

+0

はい、必要でない限り(つまり、ObservableCollectionを使用するときは)vmでディスパッチャを気にする必要はありません。通常、ほとんどのロジック(ビジネスロジックを除く)はモデルではなく、ビューモデルになっているため、モデルごとに多くの対話があってはいけません。 – Evk

関連する問題