WPF机制和原理

最近由于项目需要,自己学习了一下WPF,之前接触过sliverlight,所以对理解和编写XAML不是太陌生。其实XAML和html多少还是有点类似的。只不过XAML上添加上了自动binding机制(这里可以对比datagridview控件的binding理解一下)。

WPF有两个核心的东西,也是MVVM等一系列框架的基础。其实说白了,也就是两个重要的接口(INotifyPropertyChanged和ICommand).

INotifyPropertyChanged接口实现了数据和UI的联动,数据改变,UI界面随之改变,反之一样。(这个接口可以理解为监听,生成的Model后,通过ViewModel对Model所有相关者进行监听)

WPF其中一个比较常用的框架MVVM

下面:通过实例来解析一下MVVM(个人的理解,如果有错误,请谅解)

1.MVVM:Model-View-ViewModel

Model:就是各个实体类

View:就是显示的界面,在WPF中一般都是XAML这样的页面

ViewModel:这个是最难理解的。ViewModel官方的解释是连接Model和View的桥梁,封装和暴露一些逻辑处理方法。但个人认为,其实所有的控制和方法都在ViewModel中,可以理解为页面所有方法的一个仓库

2.MVVM的实现原理

MVVM实现简单的来说就是通过ViewModel来连接Model和View实现的。ViewModel实现了接口INotifyPropertyChanged,在Model属性改变时可以触发View页面数据改变。另外,ViewModel中的command实现ICommand这个接口,使得方法也可以直接绑定在UI控件上,省去页面后台书写控件事件的代码

下面实例代码:

Model:

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

namespace WpfApplication1
{
    
        public class DataItem
        {
            public int ID { get; set; }
            public string Name { get; set; }
        }


    
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace WpfApplication1
{
    public static class DataDemo
    {
        private static Collection<DataItem> _DataList = null;

        public static Collection<DataItem> DataList
        {
            get
            {
                if (_DataList == null)
                {
                    _DataList = InitDataList();
                }
                return _DataList;
            }
        }

        private static Collection<DataItem> InitDataList()
        {
            Collection<DataItem> lists = new Collection<DataItem>();
            for (int i = 0; i < 100; i++)
            {
                DataItem item = new DataItem();
                item.ID = i + 1;
                item.Name = "例子" + (i + 1);
                lists.Add(item);
            }
            return lists;
        }

    }

}

在Model完成后,编写ViewModel,为UI中使用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace WpfApplication1
{
    class QueryDataViewModel:INotifyPropertyChanged
    {
        #region 变量
        /// <summary> 
        /// 查询的数据 
        /// </summary> 
        private Collection<DataItem> _DataList = null;
        /// <summary> 
        /// 查询命令 
        /// </summary> 
        private ICommand _QueryCommand = null;
        /// <summary> 
        /// 搜索关键字 
        /// </summary> 
        private string _SearchText = string.Empty;
        /// <summary> 
        /// 搜索结果 
        /// </summary> 
        private string _SearchResult = string.Empty;
        #endregion

        #region 属性
        /// <summary> 
        /// 搜索关键字 
        /// </summary> 
        public string SearchText
        {
            get { return this._SearchText; }
            set
            {
                this._SearchText = value;
                if (this.PropertyChanged != null)
                    this.PropertyChanged(this, new PropertyChangedEventArgs("SearchText"));
            }
        }
        /// <summary> 
        /// 搜索结果 
        /// </summary> 
        public string SearchResult
        {
            get { return this._SearchResult; }
            set
            {
                this._SearchResult = value;
                if (this.PropertyChanged != null)
                    this.PropertyChanged(this, new PropertyChangedEventArgs("SearchResult"));
            }
        }
        /// <summary> 
        /// 查询命令 
        /// </summary> 
        public ICommand QueryCommand
        {
            get { return _QueryCommand; }
        }
        #endregion


        #region 构造函数
        public QueryDataViewModel(Collection<DataItem> dataList)
        {
            this._DataList = dataList;
            _QueryCommand = new QueryDataCommand(this);
        }
        #endregion
        #region 方法
        /// <summary> 
        /// 查询数据 
        /// </summary> 
        public void QueryData()
        {
            if (!string.IsNullOrEmpty(this.SearchText))
            {
                DataItem dataItem = null;
                foreach (DataItem item in this._DataList)
                {
                    if (item.ID.ToString() == this.SearchText)
                    {
                        dataItem = item;
                        break;
                    }
                }
                if (dataItem != null)
                {
                    this.SearchResult = string.Format("ID:{0}\nName:{1}", dataItem.ID, dataItem.Name);
                }
            }
        }
        #endregion
        #region INotifyPropertyChanged 成员
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion 
    }
}

在ViewModel中,定义了一系列的参数和方法,其中UI页面是通过ICommand这个实例来调用绑定的方法的

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace WpfApplication1
{
    class QueryDataCommand:ICommand
    {
        private QueryDataViewModel _QueryDataViewModel;
        public QueryDataCommand(QueryDataViewModel queryDataViewModel)
        {
            this._QueryDataViewModel = queryDataViewModel;
        }


        #region ICommand 成员
        public bool CanExecute(object parameter)
        {
            return true;
        }
        public event EventHandler CanExecuteChanged
        {
            add { }
            remove { }
        }
        public void Execute(object parameter)
        {
            this._QueryDataViewModel.QueryData();
        }
        #endregion 

    }
}

编写Command命令,编写前端页面

<UserControl x:Class="WpfApplication1.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid x:Name="LayoutRoot">
        <Button x:Name="btnSearch" Height="24" HorizontalAlignment="Left" 
Margin="164,8,0,0" VerticalAlignment="Top" Width="84" Content="搜索" Command="{Binding QueryCommand}"/>  //这个是绑定的方法,这里的QueryCommand就是ViewModel中的ICommand实例
        <TextBox x:Name="txtKeyword" Height="24" HorizontalAlignment="Left" 
Margin="8,8,0,0" VerticalAlignment="Top" Width="152" TextWrapping="Wrap" 
d:LayoutOverrides="HorizontalAlignment" Text="{Binding SearchText,Mode=TwoWay}"/>
        <TextBox x:Name="txtResult" HorizontalAlignment="Left" Margin="8,36,0,8" 
Width="240" TextWrapping="Wrap" d:LayoutOverrides="VerticalAlignment" Text="{Binding SearchResult,Mode=OneWay}"/>
    </Grid>

</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    

    /// <summary>
    /// UserControl1.xaml 的交互逻辑
    /// </summary>
    public partial class UserControl1 : UserControl
    {
        private QueryDataViewModel _QueryDataViewModel = null; 


        public UserControl1()
        {
            InitializeComponent();
            this._QueryDataViewModel = new QueryDataViewModel(DataDemo.DataList);
            base.DataContext = this._QueryDataViewModel;
           // this.btnSearch.Click += new RoutedEventHandler(btnSearch_Click);
        }
        void btnSearch_Click(object sender, RoutedEventArgs e)
        {
            if (this._QueryDataViewModel != null)
            {
                this._QueryDataViewModel.SearchText = this.txtKeyword.Text;
                this._QueryDataViewModel.QueryCommand.Execute(null);
            }
        } 

    }
}

 

posted @ 2016-08-31 15:38  成神之路~  阅读(3873)  评论(0编辑  收藏  举报