代码之家  ›  专栏  ›  技术社区  ›  BFree

M-V-VM,模型是否泄漏到视图中?

  •  10
  • BFree  · 技术社区  · 16 年前

    我们都知道,M-V-VM的要点是关注点的具体化。在MVVM、MVC或MVP等模式中,主要目的是将视图与数据分离,从而构建更灵活的组件。我将首先演示在许多WPF应用程序中发现的一个非常常见的场景,然后我将说明我的观点:

    假设我们有一些StockQuote应用程序,它流式处理大量报价并在屏幕上显示它们。通常情况下,你会得到:

    stockquote.cs:(型号)

        public class StockQuote
        {
           public string Symbol { get; set; }
           public double Price { get; set; }
        }
    

    stockQuoteViewModel.cs:(视图模型)

       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>
    

    然后你会得到某种服务,用新的股票报价来提供可观的收藏。

    我的问题是:在这种类型的场景中,StockQuote被视为模型,我们通过ViewModel的ObservableCollection将其公开给视图。这基本上意味着,我们的观点了解模型。这不是违反了M-V-VM的整个模式吗?或者我在这里错过了什么……?

    6 回复  |  直到 16 年前
        1
  •  3
  •   majocha    16 年前

    不,你没有公开股票报价。您只是在视图中指定一个(松散类型的)接口。视图只知道两个属性:符号和价格。只要StockQuote实现了这些功能,就可以轻松地用其他任何东西替换它。

        2
  •  8
  •   keithjgrant    16 年前

    我比MVVM更熟悉MVC,但通常认为视图将了解模型。只要模型不知道这个观点,这是可以的。

    如果这真的是出于某种原因的考虑,请查看“被动视图”设计,在该设计中,视图只知道输入到它的原始数据。

        3
  •  7
  •   Oliver Hanappi    16 年前

    在MVVM中,视图模型是视图和模型之间的某种东西,它以视图可以轻松处理的方式公开模型中的数据。在严格的MVVM应用程序中,视图不知道模型,只知道视图模型。

    在具体的示例中,不应调用视图模型 StockQuoteViewModel 但是 StockQuotesViewModel (注意复数形式)因为视图模型通过一个特定的UI集合公开了许多股票报价,而这个UI集合很容易被视图处理(因为 ObservableCollection<T> 工具 INotifyCollectionChanged<T> )集合中的项类型应为视图模型(例如 库存报价视图模型 )它显示来自单个StockQuote对象的数据。在这样的视图模型中,您可以添加逻辑,就像添加 $ -符号到 Price 等等。

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

    顺祝商祺!
    奥利弗·哈纳皮

        4
  •  3
  •   Community Mohan Dere    9 年前

    检查视频: Jason Dolinger on MVVM . 它会回答你的问题。

    另外,请参见SO问题 wpf mvvm confusion 其他资源。

        5
  •  1
  •   Dan Bryant    16 年前

    我的理解是,视图模型是对模型的,属性是对字段的。这是一个非常松散的类比,但它确实意味着,如果视图直接访问模型,那么您没有正确地进行隔离。就像包装私有字段的类中的琐碎属性一样,在将相关模型属性包装到视图模型属性中以供视图使用时,最终会出现大量重复和样板代码。这正是困扰我的模式,我仍然没有决定是否利益值得膨胀。

    在这个特定的例子中,我认为为每个stockQuote实例创建一个虚拟机是过分的,因为对于表示单个stockQuote的视图,您可能没有做任何重要的逻辑。我认为在这些小情况下,直接绑定到模型类会更干净、更易于维护。为小的案例创建一个虚拟机可以减少耦合,但是它也会增加复杂性,我认为这是一个案例一个案例地判断是否有益。

        6
  •  0
  •   deanvmc    16 年前

    也许我错了,但视图模型并不能完全封装模型。例如,您有向视图公开的股票报价,但它们应该映射到视图模型的本机属性,然后将其绑定到该属性。这就需要“清理”在将数据传输到模型/视图期间可能需要的内容。

    这样,视图只知道视图模型。它还意味着,如果模型不是遗留的,那么它可以作为接口实现,并进一步减少ViewModel之间的耦合。