最近一直搞Java,VS好久沒有打開了,感覺有必要把以前.Net體系下一些經驗給整理一下。現在越來越感覺,只會一門語言或者一種環境的開發,局限性會很大。下面先科普一下幾種常用架構模式的發展過程吧:MVC - MVP - MVVM。MVC這個不用多說了,JAVA SSH框架下就是一種經典的MVC的應用了。關於MVP之前寫過一個Asp.Net的MVP Demo有興趣的朋友可以去參考一下:http://www.cnblogs.com/CopyPaster/archive/2011/01/10/1931705.html;現在再把MVVM補充一下吧。
MVVM的背景歷史(以下內容是我對一些英文Blog部分內容的翻譯,大家湊合讀讀吧)
自從人們開始用面向接口的方式開發軟件,利用設計模式使之簡化漸漸開始流行起來。例如:MVP模式在多樣UI平台編程上的應用和流行。MVP模式是MVC模式提出后十年來的一種演變。如果你以前從未使用過MVP模式,這里有一個簡單的解釋:任何在屏幕上所能看到的被稱之為View,視圖中顯示的數據稱之為Model,View和Model之間通訊和聯系由Presenter負責。視圖依賴於Prensenter的數據處理邏輯,比如說:對於用戶輸入的響應,提供一個輸入驗證等。如果你深入了解MVP模式,建議去讀Jean-Paul Boodhoo's的文章:http://msdn.microsoft.com/en-us/magazine/cc188690.aspx
2004年,Martin Fowler發表了一篇名為PM模式的文章。PM模式與MVP模式很類似,都將視圖與其狀態和行為相分離。PM模式中不同點是:在PM中創建了一個視圖的抽象,於是視圖的功能僅僅只是呈現PM。Fowler解釋到:PM頻繁更新視圖,且兩互相同步。由此可見,PM模式邏輯處理均以同步形式存在。
2005年,恰逢微軟發布WPF和Silverlight,John Gossman,在他的博客提出了MVVM模式。MVVM模式和Fowler的PM模式一樣均定義了視圖狀態和行為的抽象。Fowler介紹的PM模式是一種開發UI獨立平台的方法。Gossman介紹的MVVM模式是一種充分利用WPF新特性創建用戶接口的標准方法。換而言之,我認為MVVM是一種特殊的PM模式,是為WPF和Silverlight平台下的開發而量身打造的。
Demo說明:
Demo本身不包含什么業務邏輯,只是寫了一些UI上的邏輯,主要的目的是展示MVVMDemo.SysFramwork.MVVM命名空間下核心代碼,以及MVVM模式下的開發方式。Demo代碼結構圖如下:
Demo UI Xaml:
<Window x:Class="MVVMDemo.UI.View.TestWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mvvm="clr-namespace:MVVMDemo.SysFramwork.MVVM;assembly=MVVMDemo.SysFramwork" xmlns:common="clr-namespace:MVVMDemo.UI.Common" Title="TestWindow" Height="300" Width="500" Name="rootControl" > <Window.Resources> <ResourceDictionary> <Style x:Key="PaymentInputTextBoxStyle" TargetType="TextBox"> <Setter Property="mvvm:CommandSource.Trigger"> <Setter.Value> <mvvm:CommandTriggerGroup> <mvvm:EventCommandTrigger RoutedEvent="FrameworkElement.Loaded" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TextBox}}}" Command="{Binding ElementName=rootControl, Path=DataContext.PaymentInputTextBoxLoadCommand}"/> <mvvm:EventCommandTrigger RoutedEvent="TextBox.GotFocus" Command="{Binding ElementName=rootControl, Path=DataContext.PaymentInputTextBoxGotFocusCommand}"/> <mvvm:EventCommandTrigger RoutedEvent="TextBox.GotMouseCapture" Command="{Binding ElementName=rootControl, Path=DataContext.PaymentInputTextBoxGotFocusCommand}"/> <mvvm:EventCommandTrigger RoutedEvent="TextBox.KeyDown" Command="{Binding ElementName=rootControl, Path=DataContext.PaymentInputTextBoxKeyDownCommand}"/> </mvvm:CommandTriggerGroup> </Setter.Value> </Setter> </Style> </ResourceDictionary> </Window.Resources> <DockPanel Margin="10,50,10,10"> <Grid DockPanel.Dock="Top" Margin="5,5,5,5"> <Grid.RowDefinitions> <RowDefinition Height="30" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition /> </Grid.ColumnDefinitions> <TextBlock Text="需要支付:" /> <TextBox Grid.Column="1" Name="tbRequiredAmount" Height="25" HorizontalAlignment="Stretch" common:TextBoxMaskBehavior.Mask="Decimal" Text="{Binding Path=RequiredAmount, UpdateSourceTrigger=PropertyChanged}"/> </Grid> <Grid DockPanel.Dock="Top" Margin="5,5,5,5" KeyboardNavigation.TabNavigation="Cycle"> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition Height="30" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition /> <ColumnDefinition Width="Auto"/> <ColumnDefinition /> </Grid.ColumnDefinitions> <TextBlock Text="現金:" /> <TextBox Grid.Column="1" Name="textBoxCash" TabIndex="1" Height="25" HorizontalAlignment="Stretch" Style="{StaticResource PaymentInputTextBoxStyle}" common:TextBoxMaskBehavior.Mask="Decimal" Tag="{Binding PaymentTypeCashRcd}" Text="{Binding Path=CashierAmount, UpdateSourceTrigger=PropertyChanged}" /> <TextBlock Grid.Column="2" Text="信用卡:" /> <TextBox Grid.Column="3" Name="textBoxCreditCard" TabIndex="2" Height="25" HorizontalAlignment="Stretch" Style="{StaticResource PaymentInputTextBoxStyle}" common:TextBoxMaskBehavior.Mask="Decimal" Tag="{Binding PaymentTypeCreditCardRcd}" Text="{Binding Path=CreditCardAmount, UpdateSourceTrigger=PropertyChanged}"/> <TextBlock Grid.Row="1" Text="支票:" /> <TextBox Grid.Column="1" Grid.Row="1" Name="textBoxCheck" TabIndex="3" Height="25" HorizontalAlignment="Stretch" Style="{StaticResource PaymentInputTextBoxStyle}" common:TextBoxMaskBehavior.Mask="Decimal" Tag="{Binding PaymentTypeCheckRcd}" Text="{Binding Path=CheckAmount, UpdateSourceTrigger=PropertyChanged}" /> <TextBlock Grid.Column="2" Grid.Row="1" Text="保險:" /> <TextBox Grid.Column="3" Grid.Row="1" Name="textBoxInsuranceCard" TabIndex="4" Height="25" HorizontalAlignment="Stretch" Style="{StaticResource PaymentInputTextBoxStyle}" common:TextBoxMaskBehavior.Mask="Decimal" Tag="{Binding PaymentTypeInsuranceCardRcd}" Text="{Binding Path=InsuranceCardAmount, UpdateSourceTrigger=PropertyChanged}" /> </Grid> <DockPanel DockPanel.Dock="Bottom" LastChildFill="False"> <Button Name="buttonConfirm" DockPanel.Dock="Right" Height="30" Width="75" Content="確認" IsEnabled="{Binding IsReadyToSubmit}" Command="{Binding Path=ButtonConfirmCommand}"> <mvvm:CommandSource.Trigger> <mvvm:CommandTriggerGroup> <mvvm:EventCommandTrigger RoutedEvent="FrameworkElement.Loaded" CommandParameter="{Binding ElementName=buttonConfirm}" Command="{Binding ElementName=rootControl, Path=DataContext.ConfirmButtonLoadCommand}"/> </mvvm:CommandTriggerGroup> </mvvm:CommandSource.Trigger> </Button> <Button Name="buttonCancel" DockPanel.Dock="Right" Height="30" Width="75" Content="取消" CommandParameter="{Binding ElementName=rootControl}" Command="{Binding Path=ButtonCancelCommand}"/> </DockPanel> </DockPanel> </Window>
Demo下載地址: