[WPF]MVVM Demo

    最近一直搞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下载地址:

http://download.csdn.net/detail/camelials/4858119

posted @ 2012-12-07 15:51  CopyPaster  阅读(8463)  评论(3编辑  收藏  举报