我继承了一个使用Prism MVVM的WPF MVVM项目。我想在视图上使用Awesomium WebControl。我在xaml中定义了WebControl,如下所示:
<awe:WebControl Name="taskBrowser" Source="http://localhost:59298/Tasks" Height="680" Width="680">
这很好用,但我还需要能够将数据从网页中的Javascript事件传递到WPF应用程序。当我在代码隐藏中执行此操作时,我有这个工作,但由于我们使用MVVM,我想以“正确”方式执行操作,并且不知道如何在后面的代码中执行,而是在ViewModel中。问题1是:我需要在ViewModel中连接DocumentReady事件,如下所示。
问题2是:我需要对ViewModel中的taskBrowser进行一些引用,以便能够执行如下所示的“taskBrowser.CreateGlobalJavascriptObject”命令,将网页js连接到WPF方法。但是在ViewModel un-MVVM中引用了taskBrowser对象?我怎么能通过这个参考?无论如何,谁能告诉我如何处理这两个问题?
public MyCodeBehindConstructor()
{
{
InitializeComponent();
...
taskBrowser.DocumentReady += TaskBrowserOnDocumentReady;
}
}
private void TaskBrowserOnDocumentReady(object sender, UrlEventArgs urlEventArgs)
{
taskBrowser.DocumentReady -= TaskBrowserOnDocumentReady;
JSObject jsobject = taskBrowser.CreateGlobalJavascriptObject("jsobject");
jsobject.Bind("callNETNoReturn", false, JSHandler);
}
private void JSHandler(object sender, JavascriptMethodEventArgs args)
{
if (args.MustReturnValue)
{
Console.WriteLine("Got method call with return request");
args.Result = "Returning " + args.Arguments[0];
}
else
{
Console.WriteLine("Got method call with no return request");
}
}
答案 0 :(得分:2)
我刚刚发布了一个新的框架,可以在C#ViewModel和awesomium之间进行所有管道工作。 基本上,您需要一次调用将viewmodel链接到IWebView,然后框架将创建将反映C#视图模型的javascripts对象。 它基于knouckout.js,所以它是完整的MVVM。 ICommand也映射到javascript方法,您可以使用knouckout标记绑定。通过INotityPropertyChanged和INotityCollectionChanged跟踪更改的集合和属性。 您可以在github上找到包含示例的整个项目:https://github.com/David-Desmaisons/MVVM-for-awesomium 例如:查看模型:
public class ViewModelBase : INotifyPropertyChanged
{
protected void Set<T>(ref T ipnv, T value, string ipn)
{
if (object.Equals(ipnv, value))
return;
ipnv = value;
OnPropertyChanged(ipn);
}
protected virtual void OnPropertyChanged(string pn)
{
if (PropertyChanged == null)
return;
PropertyChanged(this, new PropertyChangedEventArgs(pn));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Person: ViewModelBase
{
public Person()
{
Skills = new ObservableCollection<Skill>();
RemoveSkill = new RelayCommand<Skill>(s=> this.Skills.Remove(s));
}
private string _LastName;
public string LastName
{
get { return _LastName; }
set { Set(ref _LastName, value, "LastName"); }
}
private string _Name;
public string Name
{
get { return _Name; }
set { Set(ref _Name, value, "Name"); }
}
public IList<Skill> Skills { get; private set; }
public ICommand RemoveSkill { get; private set; }
}
查看(HTML +淘汰赛加价):
<!doctype html>
<html>
<head>
<title></title>
<script src="js/knockout.js" type="text/javascript"></script>
<script src="js/Ko_Extension.js" type="text/javascript"></script>
</head>
<body>
<input type="text" data-bind="value: Name, valueUpdate:'afterkeydown'" placeholder="First name" >
<ul data-bind="foreach: Skills">
<li><span data-bind="text:Type"></span>:<span data-bind="text:Name"></span>
<button data-bind="click: function (){$root.RemoveSkill($data)}">Remove skill</button></li>
</ul>
<div>
<h2><span data-bind="text: Name"></span></h2>
<h2><span data-bind="text: LastName"></span></h2>
</div>
<button data-bind="click: ChangeSkill">Click me</button>
</body>
</html>
结合:
IWebView mywebview = ...; //retrieve awesomium view wich loaded the HTML view
var datacontext = new Person();
AwesomeBinding.Bind(mywebview, datacontext, JavascriptBindingMode.TwoWay);