1. 程式人生 > >WPF之Binding深入探討

WPF之Binding深入探討

轉載於:http://blog.csdn.net/fwj380891124/article/details/8107646

1,Data Binding在WPF中的地位

程式的本質是資料+演算法。資料會在儲存、邏輯和介面三層之間流通,所以站在資料的角度上來看,這三層都很重要。但演算法在3層中的分佈是不均勻的,對於一個3層結構的程式來說,演算法一般分佈在這幾處:

A。資料庫內部。

B。讀取和寫回資料。

C。業務邏輯。

D。資料展示。

E。介面與邏輯的互動。

A,B兩部分的演算法一般都非常穩定,不會輕易去改動,複用性也很高;C處與客戶需求最緊密,最複雜,變化最大,大多少演算法都集中在這裡。D,E負責UI和邏輯的互動,也佔有一定量的演算法。

顯然,C部分是程式的核心,是開發的重中之重,所以我們應該把精力集中在C部分。然而,D,E兩部分卻經常成為麻煩的來源。首先這兩部分都與邏輯緊密相關,一不小心就有可能把本來該放在邏輯層裡面的演算法寫進這兩部分(所以才有了MVC、MVP等模式來避免這種情況出現)。其次,這兩部分以訊息或者事件的方式與邏輯層溝通,一旦出現同一個資料需要在多出展示/修改時,用於同步的程式碼錯綜複雜;最後,D和E本來是互逆的一對兒。但卻需要分開來寫-----顯示資料寫一個演算法,修改資料再寫一個演算法。總之導致的結果就是D和E兩部分會佔去一部分演算法,搞不好還會牽扯不少精力。

問題的根源在於邏輯層和展示層的地位不固定------當實現客戶需求的時候,邏輯層的確處於核心地位。但到了實現UI的時候,展示層又處於核心的地位。WPF作為一種專業的展示層技術,華麗的外觀和動畫只是它的表層現象,最重要的是他在深層次上把程式設計師的思維固定在了邏輯層,讓展示層永遠處於邏輯層的從屬地位。WPF具有這種能力的關鍵在於它引入了Data Binding概念及與之配套的Dependency Property系統和DataTemplate。

從傳統的Winform轉移到WPF上,對於一個三層程式而言,資料儲存層由資料庫和檔案系統組成,資料傳輸和處理仍然使用.NetFramework的ADO.NET等基本類(與Winform開發一樣)。展示層則使用WPF類庫來實現,而展示層和邏輯層的溝通就使用Data Binding來實現。可見,Data Binding在WPF中所起的作用就是高速公路的作用。有了這條高速公路,加工好的資料自動送達使用者介面並加以顯示,被使用者修改過的資料也會自動傳回業務邏輯層,一旦資料被加工好又會被送往介面。。。。程式的邏輯層就像是一個強有力的引擎一直在運作,用加工好的資料驅動使用者介面也文字、圖形、動畫等形式把資料顯示出來------這就是資料驅動UI。

引入Data Binding之後,D,E兩部分被簡化了很多。首先,資料在邏輯層和使用者介面直來之去、不涉及邏輯問題,這樣的使用者介面部分基本上不包含演算法:Data Binding本身就是雙向通訊,所以相當於把D和E合二為一;對於多個UI元素關注同一個資料的情況,只需要用Data Binding將這些UI元素和資料一一關聯上(以資料為中心的星形結構),當資料變化後,這些UI元素會同步顯示這一變化。前面提到的問題也都迎刃而解了。更重要的是經過這樣的優化,所有與業務邏輯相關的演算法都處在業務邏輯層,邏輯層成了一個可以獨立運轉,完整的體系,而使用者介面則不需要任何邏輯程式碼。完全依賴和從屬於業務邏輯層。這樣做有兩個顯而易見的好處,第一:如果把UI看做是應用程式的皮,把儲存層和邏輯層看作是程式的瓤,我們可以很輕易的把皮撕下來換一個新的。第二:因為資料層能夠獨立運作,自成體系,所以我們可以進行更完善的單元測試而無需藉助UI自動化測試工具----你完全可以把單元測試看作是一個“看不見的UI”,單元測試只是使用這個UI繞過真實的UI直接測試業務邏輯罷了。

2 ,  Binding 基礎

如果把Binding比作資料的橋樑,那麼它的兩端分別是源(Source)和目標(Target)。資料叢哪裡來哪裡就是源,到哪裡去哪裡就是目標。一般情況下,Binding的源是業務邏輯層的物件,Binding的目標是UI層的控制元件物件。這樣資料就會源源不斷的通過Binding送達UI介面,被UI層展現,這就完成了資料驅動UI的過程。有了這座橋樑,我們不僅可以控制車輛在源與目標之間是雙向通行還是單向通行。還可以控制資料的放行時機,甚至可以在橋上搭建一些關卡用來轉換資料型別或者檢驗資料的正確性。

通過對Binding有了一個基本概念之後,讓我們看一個最基本的例子。這個例子是建立一個簡單的資料來源並通過Binding把它連線到UI元素上。

首先,我們建立一個名為"Student"的類,這個類的例項將作為資料來源來使用。

[csharp] view plaincopyprint?
  1. publicclass Student  
  2.     {  
  3.         privatestring name;  
  4.         publicstring Name  
  5.         {  
  6.             get { return name; }  
  7.             set
  8.             {  
  9.                 name = value;  
  10.         }  
  11.     }  
這個類很簡單,簡單到只有一個string型別的Name屬性。前面說過資料來源是一個物件,一個物件本身可能會有很多資料,這些資料又通過屬性暴露給外界。那麼其中哪個元素是你想通過Binding送達UI元素的呢,換句話說,UI元素關心的是哪個屬性值的變化呢?這個屬性值稱之為Binding的路徑(Path)。但光有屬性還不行-------Binding是一種自動機制,當值變化後屬性要有能力通知Binding,讓Binding把變化傳遞給UI元素。怎樣才能讓一個屬性具備這種通知Binding值已經改變的能力呢?方法是在屬性的Set語句中激發一個PropertyChanged事件。這個事件不需要我們自己宣告,我們要做的事是讓作為資料來源的類實現System.ComponentModel名稱空間中的INotifyPropertyChanged介面。當為Binding設定了資料來源之後,Binding就會自動偵聽來自這個介面PropertyChanged事件。

實現INotifyPropertyChanged介面的類看起來是這樣:

[csharp] view plaincopyprint?
  1. publicclass Student : INotifyPropertyChanged  
  2.     {  
  3.         privatestring name;  
  4.         publicstring Name  
  5.         {  
  6.             get { return name; }  
  7.             set
  8.             {  
  9.                 name = value;  
  10.                 if (PropertyChanged != null)  
  11.                 {  
  12.                     this.PropertyChanged.Invoke(thisnew PropertyChangedEventArgs("Name"));  
  13.                 }  
  14.             }  
  15.         }  
  16.         publicevent PropertyChangedEventHandler PropertyChanged;  
  17.     }  

經過這樣一升級,當Name屬性的值發生變化時PropertyChanged事件就會被激發,Binding接收到這個事件後發現事件的訊息告訴它是Name屬性值發生了變化,於是通知Binding目標端的UI元素顯示新的值。

然後我們在窗體上準備一個TextBox和Button,程式碼如下:

[html] view plaincopyprint?
  1. <Windowx:Class="WpfApplication1.MainWindow"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         Title="MainWindow"Height="350"Width="525">
  5.     <Grid>
  6.         <TextBoxHeight="23"HorizontalAlignment="Left"Margin="185,43,0,0"Name="textBox1"VerticalAlignment="Top"Width="120"/>
  7.         <ButtonContent="Button"Height="23"HorizontalAlignment="Left"Margin="209,96,0,0"Name="button1"VerticalAlignment="Top"Width="75"Click="button1_Click"/>
  8.     </Grid>
  9. </Window>

後臺程式碼這樣寫: [csharp] view plaincopyprint?
  1. /// <summary>
  2.    /// MainWindow.xaml 的互動邏輯
  3.    /// </summary>
  4.    public partial class MainWindow : Window  
  5.    {  
  6.        Student stu = null;  
  7.        public MainWindow()  
  8.        {  
  9.            InitializeComponent();  
  10.            stu = new Student();  
  11.            Binding bind = new Binding();  
  12.            bind.Source = stu;  
  13.            bind.Path = new PropertyPath("Name");  
  14.            this.textBox1.SetBinding(TextBox.TextProperty, bind);  
  15.        }  
  16.        privatevoid button1_Click(object sender, RoutedEventArgs e)  
  17.        {  
  18.            stu.Name += "f";  
  19.            new Window1().Show();  
  20.        }  
  21.    }  

讓我們逐句解釋一下這段程式碼,這段程式碼是MainWIndow的後臺程式碼,它的前端程式碼就是上面的XAML程式碼。“Student stu;”是為MainWindow宣告一個Student型別的成員變數,這樣做的目的是為了在MainWindow的構造器和Button.Click事件處理器中都可以訪問到由它引用的Student例項(資料來源)。

在MainWindow的構造器中“InitializeComponent();”是自動生成的程式碼,用途是初始化UI元素。“stu=new Student();”這句是建立一個Student例項並用stu成員變數引用它,這個物件就是我們的資料來源。

在準備Binding的部分,先使用“Binding bind = new Binding();”宣告Binding型別變數並建立例項,然後使用“bind.Source=stu;”為Binding例項指定資料來源,最後使用“bind.Path= new PropertyPath('Name')”語句為Binding指定訪問路徑。

把資料來源和目標連線在一起的任務是使用“BindingOperations.SetBinding(...)”方法完成的,這個方法的3個引數是我們記憶的重點:

第一個引數是指定Binding的目標,本例中的this.textBoxName。

與資料來源的Path原理類似,第二個引數用於為Binding指明為Binding指明把這個資料送達目標的哪個資料。

第三個引數很明顯,就是指定使用哪個Binding例項將資料來源和目標關聯起來。

執行程式,單擊按鈕我們將會看到如下的效果圖:


通過上面的例子,我們已經在頭腦中建立起來如圖所示的模型


先用這個做基礎,後面我們將研究Binding的每個特點。

1.3         Binding的源與路徑

Binding 的源也就是資料的源頭。Binding對源的要求並不苛刻------只要它是一個物件,並且通過屬性(Property)公開自己的資料,它就能作為Binding 的源。

前面一個例子已經向大家證明,如果想讓作為Binding源的物件具有自動通知Binding自己屬性值已經已經變化的能力。那麼就需要讓類實現INotifyChanged介面並在屬性的Set語句中激發PropertyChanged事件。在日常生活中,除了使用這種物件作為資料來源之外,我們還有更多的選擇,比如控制元件把自己的容器或子集元素當源、用一個控制元件做為另一個控制元件的資料來源,把集合作為ItemControl的資料來源、使用XML作為TreeView或Menu的資料來源。把多個控制元件關聯到一個“資料制高點”上,甚至乾脆不給Binding指定資料來源、讓他自己去找。下面我們就分述這些情況。

1.3.1       把控制元件作為Binding源與Binding標記擴充套件。

前面講過,大多數情況下Binding的源是邏輯層物件,但有的時候為了讓UI產生聯動效果也會使用Binding在控制元件間建立關聯。下面的程式碼是吧一個TextBox的Text屬性關聯到Slider的Value的屬性上。

[html] view plaincopy

相關推薦

WPFBinding深入探討

轉載於:http://blog.csdn.net/fwj380891124/article/details/8107646 1,Data Binding在WPF中的地位 程式的本質是資料+演算法。資料會在儲存、邏輯和介面三層之間流通,所以站在資料的

WPF Binding 資料驅動UI—實戰

1、一個TextBox顯示另一個TextBox文字的第4個字元 <TextBox x:Name="tb1"/> <!--tb2繫結:單向繫結 tb1的Text屬性第4個字元-->

WPFBinding

Binding類:提供對繫結定義的高階訪問,該繫結連線繫結目標物件(通常為 WPF 元素)的屬性和任何資料來源(例如資料庫、XML 檔案,或包含資料的任何物件)。 Mode 屬性:獲取或設定一個值,該值指示繫結的資料流方向。 (Default:使用繫結目

WPF Binding 對資料的校驗與轉換(三)

# 一、前言 ​ Binding 的作用就是架在 **Source** 和 **Target** 之間的橋樑,資料可以在這座橋樑的幫助下來流通。就像現實中的橋樑會設定一些關卡進行安檢一樣,Binding 這座橋上也可以設定關卡對資料的有效性進行校驗。不僅如此,當兩端要求使用不同的資料型別時,我

OpenCV探索路(十六):圖像矯正技術深入探討

double gb2 教科書 長方形 strong fine open lines 導致 剛進入實驗室導師就交給我一個任務,就是讓我設計算法給圖像進行矯正。哎呀,我不太會圖像這塊啊,不過還是接下來了,硬著頭皮開幹吧! 那什麽是圖像的矯正呢?舉個例子就好明白了。 我的好朋友小

深入探討WPF的ListView控件

示例 hand lib ems n) sort origin 分數 view 接上一篇博客初步探討WPF的ListView控件(涉及模板、查找子控件) 我們繼續探討ListView的用法 一、實現排序功能 需求是這樣的:假如我們把學生的分數放

c++ 入門深入探討拷貝函式和賦值運算子

在c++入門之深入探討類的一些行為時,說明了拷貝函式即複製建構函式運用於如下場景: 物件作為函式的引數,以值傳遞的方式傳給函式。  物件作為函式的返回值,以值的方式從函式返回 使用一個物件給另一個物件初始化 針對上述的三種情況,實際上很多時候,我們都會用到;如果我們採用系統預設的拷貝函式

WPF應用BindingItemsSource

一、ListBox顯示簡單的列表資訊(未使用DataTemplate) (1) Student類 public class Student { public string Name { get; set; } public

WPF應用Binding資料轉換

有時資料來源的型別與目標型別不一致時,需要把源通過一定的轉換之後才能繫結到目標之上。 本例: (1) 把車的型別轉換成車所對應的圖片路徑; (2) 把車的執行狀態轉換成CheckBox的狀態; 1、類/型別定義 public enum Category//車的型

WPF應用BindingMultiBinding

有時目標繫結多個源的資料,此時需要使用多路繫結MultiBinding。 本例4個TextBox(textBox1, textBox2, textBox3, textBox4)及一個按鈕,當textBox1與textBox2內容相同,並且textBox3與textBox4

WPF Data Binding指定源(Source)的幾種方法【三】

    Binding的源是資料的來源,所以,只要一個物件包含資料並且能夠通過屬性將資料暴露出來,它就能當作Binding的源來使用。包含資料的物件比比皆是,但必須為Binding的Source指定合

【轉載文章】拜占庭將軍問題深入探討

監聽 修改 最終 重寫 其中 聯系 默認 命題 不存在 原文地址:http://www.8btc.com/baizhantingjiangjun part1: 拜占庭將軍問題是什麽? 1.1 拜占庭將軍問題場景 1.2 與拜占庭將軍相關問題:兩軍問題 part

Android——AIDL深入

you widget avi net 存在 rate 優點 font 接口 轉載請註明出處:http://blog.csdn.net/l1028386804/article/details/47071927 在上一篇博文《Android之——AIDL小結》中,我們簡介

WPF樣式——style

很難 emp private target void dict 右鍵 所有 winform wpf這門編寫winform程序的技術相比常規的winform技術有一個很顯著的特點——炫! 怎麽才能炫起來呢? 我們都知道常規的winform技術就是拖控件,總的來說想用常規的wi

WPF數據觸發器 改變控件背景色或閃爍

cti get 背景 anim soft reg using round markup 需求,很多矩形表示桶,其中:空桶=紅色,滿桶=綠色,使用中=紅綠閃爍。 <Window x:Class="FlickerDemo.MainWindow" xmln

深入探討Linux靜態庫與動態庫的詳解(轉)

share 分享 命名 one .com 過程 程序 簡單介紹 mage 2.生成動態庫並使用 linux下編譯時通過 -shared 參數可以生成動態庫(.so)文件,如下 庫從本質上來說是一種可執行代碼的二進制格式,可以被載入內存中執行。庫分靜態庫和動態庫兩種。

mysql left join的深入探討

left join 關於 簡單 mysql eight src 如何 isa sele 即使你認為自己已對 MySQL 的 LEFT JOIN 理解深刻,但我敢打賭,這篇文章肯定大致也許可能讓你學會點東西! ON 子句與 WHERE 子句的不同 一種更好地理解帶有 WHE

關於shared pool的深入探討(六)-高Latch競爭案例

size ... ogre poi hash map exec invalid star alink 研究了幾天shared pool,沒想到忽然就撞到問題上來了.作為一個案例寫出來給大家參考一下吧. 問題起因是公司做短信群發,就是那個18萬買的4000字的短信小說(噓,小

關於shared pool的深入探討(三)

dbm num events tab names size ntc data lag 基本命令: ALTER SESSION SET EVENTS ‘immediate trace name LIBRARY_CACHE level LL‘; 其中LL代表Level級別,對於

WPF自學入門(七)WPF 初識Binding

依賴項 RM opacity 自身 date 數據傳遞 one 忽略 chang 今天記錄一下Binding的基礎和具體的使用方法,說起這個Binding,在WPF中,Binding是很重要的特征,在傳統的Windows軟件來看,大多數都是UI驅動程序的模式,