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);
            }
        } 

    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM