众所周知,M-V-VM的重点在于关注的问题。在MVVM,MVC或MVP等模式中,主要目的是将View与Data分离,从而构建更灵活的组件。我将首先演示在许多WPF应用程序中找到的非常常见的场景,然后我会说明一点:
假设我们有一些StockQuote应用程序可以流式传输一堆引号并在屏幕上显示它们。通常,你有这个:
StockQuote.cs :(型号)
public class StockQuote
{
public string Symbol { get; set; }
public double Price { get; set; }
}
StockQuoteViewModel.cs :( ViewModel)
public class StockQuoteViewModel
{
private ObservableCollection<StockQuote> _quotes = new ObservableCollection<StockQuote>();
public ObservableCollection<StockQuote> Quotes
{
get
{
return _quotes;
}
}
}
StockQuoteView.xaml(查看)
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.DataContext>
<local:StockQuoteViewModel/>
</Window.DataContext>
<Window.Resources>
<DataTemplate x:Key="listBoxDateTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Symbol}"/>
<TextBlock Text="{Binding Price}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemTemplate="{StaticResource listBoxDateTemplate}" ItemsSource="{Binding Quotes}"/>
</Grid>
</Window>
然后你会得到某种服务,用新的StockQuotes为ObservableCollection提供服务。
我的问题是:在这种情况下,StockQuote被认为是Model,我们通过ViewModel的ObservableCollection将它暴露给View。这基本上意味着,我们的View拥有模型的知识。这是否违反了M-V-VM的整个范式?或者我在这里错过了什么......?
答案 0 :(得分:8)
我比MVVM更熟悉MVC,但是人们普遍认为View会知道模型。只要模型不了解View就可以了。
如果出于某种原因这确实是一个问题,请查看“被动视图”设计,其中View只知道提供给它的原始数据。
答案 1 :(得分:7)
在MVVM中,视图模型位于视图和模型之间,它以一种可以由视图轻松处理的方式公开模型中的数据。在严格的MVVM应用程序中,视图不了解模型,只知道视图模型。
在您的具体示例中,视图模型不应该被称为StockQuoteViewModel
而是StockQuotesViewModel
(注意复数),因为视图模型通过特定的ui集合公开了许多股票报价,这很容易视图处理(因为ObservableCollection<T>
实现INotifyCollectionChanged<T>
)。集合中的项目类型应该是一个视图模型(例如StockQuoteViewModel
),它公开来自单个StockQuote对象的数据。在这样的视图模型中,您可以添加逻辑,例如向$
添加Price
- 符号,依此类推。
在视图模型中公开一些模型对象通常更容易,但正确的方法是为每个模型类创建一个视图模型。
最诚挚的问候,
Oliver Hanappi
答案 2 :(得分:3)
没有。您没有暴露StockQuote。您只是在视图中指定(松散类型)接口。视图只知道两个属性:符号和价格。只要它实现了那些,你就可以轻松地用其他任何东西替换StockQuote。
答案 3 :(得分:3)
查看视频:Jason Dolinger on MVVM。它会回答你的问题。
另外,请参阅问题wpf mvvm confusion以获取更多资源。
答案 4 :(得分:1)
我的理解是,ViewModel属于模型,属性属于Fields。这是一个非常宽松的类比,但如果您的View直接访问您的模型,它确实意味着您没有正确隔离。就像包装私有字段的类中的普通属性一样,在ViewModel属性中包含相关的Model属性以供View使用时,最终会得到大量的复制和样板代码。这种情况困扰着我,我仍然没有决定这些好处是否值得臃肿。
在这个特定的例子中,我认为为每个StockQuote实例创建一个VM会有点过分,因为您可能没有为代表单个StockQuote的View做任何重要逻辑。我认为在这些小的情况下,直接绑定到Model类会更清晰,更易于维护。为小案例创建VM会减少耦合,但这也会增加复杂性,我认为这是一个判断是否有益的判断调用。
答案 5 :(得分:0)
也许我有这个错误,但不是完全封装模型的viewmodel的想法。例如,您有暴露给视图的股票报价,但它们应该映射到viewmodel本机的属性,然后绑定到该属性。这是为了在将数据传输到模型/视图期间可能需要“清理”。
这样,视图才知道视图模型。这也意味着如果模型不是遗留的,它可以作为接口实现,并进一步减少视图模型之间的耦合。