MV-VM,是不是模型泄漏到视图中?

BFr*_*ree 10 c# wpf mvvm

众所周知,MV-VM的重点在于关注问题.在MVVM,MVC或MVP等模式中,主要目的是将View与Data分离,从而构建更灵活的组件.我将首先演示在许多WPF应用程序中发现的非常常见的场景,然后我会说明我的观点:

假设我们有一些StockQuote应用程序可以流式传输一组引号并在屏幕上显示它们.通常,你有这个:

StockQuote.cs :(型号)

    public class StockQuote
    {
       public string Symbol { get; set; }
       public double Price { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

StockQuoteViewModel.cs :( ViewModel)

   public class StockQuoteViewModel
   {
      private ObservableCollection<StockQuote> _quotes = new ObservableCollection<StockQuote>();

      public ObservableCollection<StockQuote> Quotes 
      {
         get
         {
            return _quotes;
         }
      }
   }
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

然后你会有一些服务可以用新的StockQuotes为ObservableCollection提供信息.

我的问题是:在这种情况下,StockQuote被认为是Model,我们通过ViewModel的ObservableCollection将它暴露给View.这基本上意味着,我们的View拥有模型的知识.这不违反MV-VM的整个范式吗?或者我在这里错过了什么......?

kei*_*ant 8

我对MVC比MVVM更熟悉,但人们普遍认为View将具备Model的知识.只要模型不了解View,这是可以的.

如果出于某种原因这确实是一个问题,请查看"被动视图"设计,其中View只知道提供给它的原始数据.

  • 正是我打算输入的内容.视图必须知道关于模型的*某些东西*,否则它是什么视图? (5认同)

Oli*_*ppi 7

在MVVM中,视图模型位于视图和模型之间,它以一种可以由视图轻松处理的方式公开模型中的数据.在严格的MVVM应用程序中,视图不了解模型,仅了解视图模型.

在您的具体示例中,不应调用视图模型,StockQuoteViewModel而是StockQuotesViewModel(注意复数),因为视图模型通过特定的ui集合公开了许多股票报价,该集合很容易被视图处理(因为ObservableCollection<T>工具INotifyCollectionChanged<T>).集合中的项目类型应该是视图模型(例如StockQuoteViewModel),它从单个StockQuote对象公开数据.在这样的视图模型中,您可以添加逻辑,例如添加$-symbol Price等等.

在视图模型中公开一些模型对象通常更容易,但正确的方法是为每个模型类创建一个视图模型.


诚挚的问候,Oliver Hanappi


maj*_*cha 3

不,您没有公开 StockQuote。您仅在视图中指定一个(松散类型的)接口。该视图只知道两个属性:符号和价格。您可以轻松地将 StockQuote 替换为其他任何内容,只要它实现了这些功能即可。