1

我有一个实现 WPF WebBrowser 控件的应用程序。它加载一个页面,其中包含一些必须从我的应用程序(可能来自其他线程)调用的 JS 函数。最好,我想坚持 MVVM 模式,并将用于解析函数返回的代码保留在模型中。调用 WebBrowser 对象的 InvokeScript 方法应该发生在 Dispatcher 线程上(因此也发生在视图中),因为它是一个 UI 元素。

我目前为完成这项工作而采取的步骤是(大致是伪的):

- 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)

这会导致模型和视图之间(通过视图模型)进行相当多的来回通信。由于我对 WPF(或 MVVM)没有那么丰富的经验,我想知道是否有一种更简洁的方式来完成这项任务(我的意思是更简洁:模型、视图模型和视图之间的调用和事件更少)。

4

2 回答 2

0

因此,MVVM 的主要目的是将接口(特定于平台:windows\android\ios\windows phone 等)与其他所有接口分开,以便您可以在不同平台上重用逻辑(viewmodel\model)。所以很明显你不能直接从 viewmodel 调用 InvokeScript - 但不是因为调度程序。Dispatcher 你可以抽象出来(例如),因为在某些情况下你需要在你的视图模型中使用它。所以通常当视图模型需要对视图执行操作时 - 使用事件(或只是委托):

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
    }
}
于 2016-04-01T22:19:17.410 回答
0

我知道这不完全是您问题的答案,但它可能会在将来对您有更多帮助。看一下名为 CefSharp 的组件。这是围绕 Chrome 嵌入式框架的 ac# 包装器。它对 MVVM 非常友好,它是开源的、免费的,并且相当容易开发。我最近从另一个 Chrome 包装器 (Awesomium) 迁移到它,并且对它非常满意。

CefSharp 允许您从页面调用 js 函数,它甚至支持这些调用的 async/await。

于 2016-04-01T22:06:46.980 回答