2013-03-08 87 views
3

我正在尝试学习MVVM并使用MVVM指示灯与我的手机应用程序,但我对如何访问某些信息感到困惑。应该控制在ViewModel中吗?

我想尽可能不使用事件背后的代码,因为这似乎不是真正的MVVM方式,但我遇到了一个问题,我不知道该怎么做。

我使用Google身份验证,并在每次浏览器加载后检查Naviagted事件。

public ICommand BrowserNavigated 
{ 
    get 
    { 
     return new RelayCommand<NavigationEventArgs>(e => 
     { 
     var d = e; 
     var a = d; 
     }); 
    } 
} 

但是我还需要实际的对象控制(我想访问该页面吐回了HTML),但我不知道如何得到它。

private void wbGoogle_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e) 
    { 
     var d = e; 
     var d2 = d; 
    } 
在上面的代码我可以只投“发送”到Web浏览器的对象,但我做了MVVM方式,我不知道如何访问它

我应该有我的ViewModel的WebBrowser的另一个属性或东西?

回答

1

在MVVM中,后面的代码是允许的,但也许绑定是首选。但是,不允许使用GUI控件/事件(硬耦合)。

可能有许多方法可以避免后面的代码,但是如果您必须处理事件,请将数据从事件中取出并在您的代码中设置ViewModel上的属性,那么这是更好的方法比将UI代码添加到ViewModel显然不符合MVVM。

也许你可以创建一些EventTrigger,它为Web浏览器设置一个属性,你可以绑定它来创建一个可以在XAML中设置的可重用触发器? (可能有许多方法可以巧妙地避免代码隐藏并创建可重用代码)

0

您的ViewModel应该完全不了解视图或特定控件。是否保持你的观点的代码隐藏是一个宗教问题。

如果你想保持它的干净,我建议尽可能,有一些概念,它可以让你这样做。

首先,你需要设计的方式你查看/视图模型的关系,即相关视图模型的所有数据存在“随时”的视图模型或可通过ICommandCommandParameter被传递到视图模型。在你的情况下,如果Web浏览器的页面由ViewModel控制(即可能设置),ViewModel应该保存一个属性,该属性绑定到浏览器的Source属性。如果在执行BrowserNavigated时ViewModel只需'知道'Uri,只需将它作为CommandParameter传递即可。

其次,对于您的特定情况,当WebBrowser的Navigated事件引发时,您希望在ViewModel上执行命令。一如既往,有几个选择。我更喜欢框架附带的选项:EventTriggerSystem.Windows.Interactivity允许您通过绑定将任何控件的任何事件转发给命令。

这种方式,开放的我们可以从视图模型设置:

<WebBrowser Source="{Binding BrowserPageUri}" Name="wbGoogle"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="Navigated" > 
      <i:InvokeCommandAction Command="{Binding BrowserNavigated}" /> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</WebBrowser> 

这样,您就可以处理URI作为命令的参数:

<WebBrowser Name="wbGoogle"> 
     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="Navigated" > 
       <i:InvokeCommandAction Command="{Binding BrowserNavigated}" 
             CommandParameter="{Binding Source, ElementName=wbGoogle}" /> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 
    </WebBrowser> 

当然,这只是让您访问WebBrowser中的页面的Uri,而不是页面本身。如果您需要绑定到页面对象本身,则需要扩展带有附加属性的WebBrowser,以使Document属性可绑定。这是相当直接的:

Attached Document property for WebBrowser

这个属性附加到你的web浏览器后,你可以定义web浏览器的绑定,就像在上面的代码,只需用附加属性,而不是Source财产。

注意,对于绑定到一个附加属性的语法是:

{Binding Path=(WebBrowserExtentions.Document)} 
0

MVVM可以进行数据绑定和使用工具包一样MVVMLight,事件与用户交互的处理也可以巧妙地处理很大用。

但是有时候,像WebBrowserControlApplicationBar这样的控件对此提出了挑战。他们可能很难或不可能与事件触发器绑定,或者有复杂的行为。在这些情况下,如果您处理在View代码中从控件获取信息的过程并将简单消息发送到VM,则会更简单。当然你可以创建一个事件来更新一个属性,写一个附加属性,或者使用第三方库;有些案例证明了这种做法。

在你的榜样,我个人使用代码隐藏来处理Navigated事件和发下来含一切VM要一气呵成消息(或在VM方法调用)。

例如:

private void wbGoogle_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e) 
{ 
    var vm = (TypeOfMyViewModel) this.DataContext; 
    //... read your HTML, get URL etc ... 
    vm.WebBrowserNavigatedTo(url, html, loadTime); 
} 

同样,如果从你的虚拟机引发的事件会导致很多事情在视图中发生有那么一刻,它是简单的发送消息或事件到您的视图,并让该视图更新代码中的控件。

关键是保持MVVM的角色不同,例如,以避免ViewModel直接依赖View。接口可以很好地帮助MVVMLight及其替代品附带的消息传递。

+0

雅这就是我正在考虑使用web浏览器的事件背后的代码。不确定你的意思是“发送包含虚拟机想要的所有内容的消息(或者在你的虚拟机上进行方法调用)。”还有其他什么情况下只使用代码更好? – chobo2 2013-03-08 22:55:38

+0

'OnNavigatedTo'和'OnNavigatedFrom'立即回想起来...... – 2013-03-08 22:57:10

+0

让我困惑的另一件事是如果你使用MVVM,你会如何像进度条那样做?我认为我看到人们使用虚拟机中的可见性,但这不像是将UI控件引入虚拟机? – chobo2 2013-03-08 23:00:04

相关问题