码迷,mamicode.com
首页 > Windows程序 > 详细

第5篇 WPF C# 数据绑定Model-View-ViewModel模式

时间:2015-11-02 13:46:36      阅读:365      评论:0      收藏:0      [点我收藏+]

标签:

第5篇  WPF C# 数据绑定Model-View-ViewModel模式

参考资料:

John Sharp:《Microsoft Visual C# 2013 Step by Step》

周 靖 译:John Sharp《Visual C# 2012从入门到精通》

前言

Model-View-ViewModel模式即MVVM模式编程涉及五个文件:

1、MainWindow.xaml文件      UI界面文件

2、MainWindow.xaml.cs文件      UI架构文件

3、ViewModel.cs文件             视图模型文件

4、DataLib.cs数据类库文件        数据元素类库文件

5、Command.cs文件          UI命令文件

上面的文件名斜体为自由定义。正体为参考资料资料定义。

1界面文件

MainWindow.xaml

<Window x:Class="StudyDisplay.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Background="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}">
        <!-- Grid定义 -->
        <Grid.ColumnDefinitions>
            ……
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" Grid.Column="0" Grid.RowSpan="5" Background="{DynamicResource {x:Static SystemColors.ActiveCaptionBrushKey}}" />
        <StackPanel Grid.Row="0" Grid.Column="1" Grid.RowSpan="5" Background="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionBrushKey}}" />

        <!--1-->
        <StackPanel Grid.Row="0" Grid.Column="2" Style="{StaticResource TheStackPanelStyle}" >    ……    </StackPanel>
        
        <!--2-->
        <StackPanel Grid.Row="1" Grid.Column="2"  Style="{StaticResource TheStackPanelStyle}" >
            <StackPanel>
                <Label Style="{StaticResource TheLabeltyle}">采样周期</Label> 
                <TextBox Style="{StaticResource TheTextBoxStyle}"
                         Name="inputSC"
                         Text="{Binding Current.SampleCircle,Mode=TwoWay}" 
                         GotFocus="inputSC_GotFocus" 
                         PreviewMouseLeftButtonDown="inputSC_PreviewMouseLeftButtonDown"
                         />   
            </StackPanel>
            <StackPanel>
                <Label Style="{StaticResource TheLabeltyle}">公制/英制</Label>
                <ComboBox Style="{StaticResource TheComboBoxStyle}" Background="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}">
                    <ComboBoxItem Style="{StaticResource ThComboBoxItemStyle}">公制</ComboBoxItem>
                    <ComboBoxItem Style="{StaticResource ThComboBoxItemStyle}">英制</ComboBoxItem>
                    <ComboBoxItem Style="{StaticResource ThComboBoxItemStyle}">华制</ComboBoxItem>
                </ComboBox> 
            </StackPanel>
            <StackPanel>
                <Label Style="{StaticResource TheLabeltyle}">采样周期1</Label>
                <TextBox Style="{StaticResource TheTextBoxStyle}"
                         Name="outputSC"                        
                         Text="{Binding Current.SampleCircle,Mode=TwoWay}" 
               GotFocus="outputSC_GotFocus" /> </StackPanel> <StackPanel> <Label Style="{StaticResource TheLabeltyle}">公制/英制1</Label> <ComboBox Style="{StaticResource TheComboBoxStyle}" Background="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}"> <ComboBoxItem Style="{StaticResource ThComboBoxItemStyle}">公制</ComboBoxItem> <ComboBoxItem Style="{StaticResource ThComboBoxItemStyle}">英制</ComboBoxItem> <ComboBoxItem Style="{StaticResource ThComboBoxItemStyle}">华制</ComboBoxItem> </ComboBox> </StackPanel> </StackPanel> <!--3--> <StackPanel Grid.Row="2" Grid.Column="2" Style="{StaticResource TheStackPanelStyle}"> <CheckBox Content="CheckBox" Checked="CheckBox_Checked_1" /> <CheckBox Content="CheckBox" Checked="CheckBox_Checked" /> <CheckBox Content="CheckBox" /> <CheckBox Content="CheckBox" Checked="CheckBox_Checked" /> <CheckBox Content="CheckBox" /> <CheckBox Content="CheckBox" /> <CheckBox Content="CheckBox" /> </StackPanel> <!--4--> <StackPanel Grid.Row="3" Grid.Column="2" Style="{StaticResource TheStackPanelStyle}">…… </StackPanel>
<!--5--> <StackPanel Grid.Row="4" Grid.Column="2" Style="{StaticResource TheStackPanelStyle}">…… </StackPanel>
</Grid> <!-- <Page.TopAppBar > <AppBar IsSticky="True"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <AppBarButton x:Name="previousCustomer" Icon="Back" Command="{Binding Path=PreviousCustomer}"/> <AppBarButton x:Name="nextCustomer" Icon="Forward" Command="{Binding Path=NextCustomer}"/> </StackPanel> </AppBar> </Page.TopAppBar> --> </Window>

如上列代码中粗体所示。绑定语句为:

Text="{Binding Current.SampleCircle,Mode=TwoWay}"

与简单的数据绑定相比,增加了 Current. 

代码末尾一段(<Page.TopAppBar ></Page.TopAppBar>)在Win7下无法运行,是Win8的AppBar控件。用"Back""Forward"按钮分别绑定命令上一个、下一个命令。该命令实现:数据引导ID的增减1,从而使上列绑定数据在视图模型中列出的各个数据表绑定。

2、架构文件

 MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace StudyDisplay
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        //架构绑定
        public MainWindow()
        {
            InitializeComponent();
DataLib dataLib = new DataLib { SampleCircle = "John" };
       //在MainPage构造器中删除创建Customer对象的代码,替换成创建ViewModel类实例 的一个语句。
ViewModel viewModel = new ViewModel();
//修改设置MainPage对象的DataContext属性的语句,来引用新的ViewModel对象。
this.DataContext = viewModel;
     }
     //交互逻辑
        private void inputSC_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
           // var control = sender as System.Windows.Controls.TextBox;
            //if (control == null)
               // return;
           // Keyboard.Focus(control);
           // e.Handled = true;
        }
        private void inputSC_GotFocus(object sender, RoutedEventArgs e)
        {
           // inputSC_GotFocus.SelectAll();
        }
        private void outputSC_GotFocus(object sender, RoutedEventArgs e)
        {
            //outputSC_GotFocus.SelectAll();
        }       
    }
}

在MainPage构造器中删除创建Customer对象的代码,替换成创建ViewModel类实例 的一个语句。修改设置MainPage对象的DataContext属性的语句,来引用新的ViewModel对象。如加粗的语句所示。

 3、视图模型文件

项目资源管理器—>项目—>右键|添加—>类—>文件名:ViewModel.cs 新建ViewModel.cs文件。

ViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.ComponentModel;

namespace StudyDisplay
{
    public class ViewModel : INotifyPropertyChanged
    {
        private List<DataLib> dataLib;
        private int currentDataLib;
        //添加NextCustomer和PreviousCustomer自动属性。
        //视图将绑定到这些Command对象,允许在客户之间导航。
        public Command NextDataLib { get; private set; }
        public Command PreviousDataLib { get; private set; }
        //
        public ViewModel()                      //ViewModel构造器
        {
            this.currentDataLib = 0;
            this.IsAtStart = true;              //设置IsAtStart和IsAtEnd属性
            this.IsAtEnd = false;               //设置IsAtStart和IsAtEnd属性
            //设置NextCustomer和PreviousCustomer属性来引用新的Command对象,
            this.NextDataLib = new Command(this.Next, () =>
                { return this.dataLib.Count > 0 && !this.IsAtEnd; });   //Lambda表达式
            this.PreviousDataLib = new Command(this.Previous, () =>
                { return this.dataLib.Count > 0 && !this.IsAtStart; }); //Lambda表达式
            //1、ViewModel类将一个List<Customer>对象作为它的模型,构造器用示例数据填充该列表。
            this.dataLib = new List<DataLib>
            {
                new DataLib
                {
                    CustomerID = 1,
                    SampleCircle = "John",
                },
                new DataLib
                {   
                    CustomerID = 2,
                    SampleCircle = "Diana",
                },
                new DataLib
                {
                    CustomerID = 3,
                    SampleCircle = "Francesca",
                }
            };
            //
        } 
//添加以下字段和属性。将用这两个属性跟踪ViewModel的状态。 //如果ViewModel的currentCustomer字段定位在customers集合起始处,IsAtStart属性将设为true, //如果定位在customers集合末尾, IsAtEnd属性将设为true。 private bool _isAtStart;      public bool IsAtStart { get { return this._isAtStart; } set { this._isAtStart = value; this.OnPropertyChanged("IsAtStart"); } } private bool _isAtEnd; public bool IsAtEnd { get { return this._isAtEnd; } set { this._isAtEnd = value; this.OnPropertyChanged("IsAtEnd"); } } /* */ public DataLib Current { get { return this.dataLib[currentDataLib]; } } //将加粗的私有方法Next和Previous添加到ViewModel类,放到Current属性之后。 //注意 Count属性返回集合中的数据项的数量,但记住集合项的编号是从0到Count – 1。 //这些方法更新currentCustomer变量来引用客户列表中的下一个(或上一个)客户。 //注意,方法负责维护IsAtStart和IsAtEnd属性的值,并通过为Current属性引发 //PropertyChanged事件来指出当前客户已发生改变。两个方法都是私有方法,它 //们不应从ViewModel类的外部访问。外部类通过命令来运行这些方法。命令将在下面的步骤中添加。 //!+++!此处涉及自定义的变量 private void Next() { if (this.dataLib.Count - 1 > this.currentDataLib) { this.currentDataLib++; this.OnPropertyChanged("Current"); this.IsAtStart = false; this.IsAtEnd = (this.dataLib.Count - 1 == this.currentDataLib); } } private void Previous() { if (this.currentDataLib > 0) { this.currentDataLib--; this.OnPropertyChanged("Current"); this.IsAtEnd = false; this.IsAtStart = (this.currentDataLib == 0); } } //记住,视图在控件的数据绑定表达式中通过Current属性来引用数据。ViewModel类移动至不同的客户时, //必须引发PropertyChanged事件通知视图所显示的数据发生改变。 public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } }

 

         

 

第5篇 WPF C# 数据绑定Model-View-ViewModel模式

标签:

原文地址:http://www.cnblogs.com/moiska/p/4929752.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!