武漢北大青鳥 > IT技術教程 > .NET技術教程 >

分析多路的 Binding

時間:2015-05-07來源:北大青鳥徐東校區

 分析這樣一個需求——UI上有若干個文本框和一個“提交”按鈕,這些文本框都是用戶必須填寫的,如果不都填寫,提交按鈕是不可用的。

 
   習慣了使用WinForm的同學可能腦子里已經開始飛速地搜尋使用Event來解決的方案了。實際上,在WPF里使用多路Data Binding將非常簡單。所謂“多路Binding(也可以叫復合Binding)”就是指某個元素的Dependency Property的值不是由單一的數據源來決定,而是由多個數據源(通過一定邏輯)共同決定的,我們一般會把邏輯寫在Converter里。是不是頗有些“腳踩N條船”的意思?
 
   多路Binding使用的類是MultiBinding類,這個類實際上就是對一組Binding對象的包裝——本質上并沒有影響Binding是“一對一”的基本理論。
 
   下面讓我們動手實現這個例子,因為大家已經對WPF的基本編程很熟悉了,所以我只把核心代碼寫在下面(又一次,我違反代碼維護性原則,把它們寫在了窗體的構造程序中)。
 
  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Windows;

  6. using System.Windows.Controls;

  7. using System.Windows.Data;

  8. using System.Windows.Documents;

  9. using System.Windows.Input;

  10. using System.Windows.Media;

  11. using System.Windows.Media.Imaging;

  12. using System.Windows.Navigation;

  13. using System.Windows.Shapes;

  14. namespace MultiBindingSample

  15. {

  16.    public partial class Window1 : Window

  17.    {

  18.        public Window1()

  19.        {

  20.            InitializeComponent();

  21.            // 準備作為基礎的“一對一”子Binding

  22.            Binding b1 = new Binding("Text") { Source = this.textBox1 };

  23.            Binding b2 = new Binding("Text") { Source = this.textBox2 };

  24.            Binding b3 = new Binding("Text") { Source = this.textBox3 };

  25.            Binding b4 = new Binding("Text") { Source = this.textBox4 };

  26.            // 準備一對一Binding的包裝箱,并把子Binding裝進去

  27.            MultiBinding mb = new MultiBinding();

  28.            mb.Bindings.Add(b1);

  29.            mb.Bindings.Add(b2);

  30.            mb.Bindings.Add(b3);

  31.            mb.Bindings.Add(b4);

  32.            // 為多路Binding配備決策邏輯(它是一個多路Converter),并設置為OneWay

  33.            mb.Converter = new SubmitEnableConverter();

  34.            mb.Mode = BindingMode.OneWay;

  35.            // 為Button設置多路Binding

  36.            this.button1.SetBinding(Button.IsEnabledProperty, mb);

  37.        }

  38.    }

  39.    public class SubmitEnableConverter : IMultiValueConverter // 注意Converter基類的變化

  40.    {

  41.        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)

  42.        {

  43.            // 使用Lambda表達式判斷,只要有空的,就返回false

  44.            return !values.Cast<string>().Any(text => string.IsNullOrEmpty(text));

  45.        }

  46.        // 因為是只從數據源到目標的方向Binding,所以,這個函數永遠也不會被調到

  47.        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)

  48.        {

  49.            throw new NotImplementedException();

  50.        }

  51.    }

  52. }

   整個程序并沒有什么難理解的,與我們以前學習的Binding較大的區別就在它的Converter上,這回使用的Converter,其基接口是IMultiValueConverter,而不是先前我們使用的IValueConverter。這個接口仍然只有兩個函數需要實現一下。又因為我們這次使用的是OneWay模式,所以,代碼中只有Convert函數中包含邏輯。
 
   請大家注意,Convert函數中重要的就是它的values參數。這個參數是一個數組,這個數組里包含的就是從一對一子Binding里送來的值(在我們的程序里,就是4個TextBox的Text屬性值)。數組是可被索引的,這就意味著values里面的值是有順序的!那么這個順序是什么呢?這個順序就是你調用MultiBinding.Bindings.Add(...)添加子Binding順序——我認為這里是多路Binding一個小小的敗筆——這樣,寫出來的代碼會比較脆弱、順序不能變,而且比較隱晦。換句話說,后來的程序員如果改變一下Add的順序,就有可能導致程序出現很難測出的bug。
 
   本例中,values[0]對應的是textBox1.Text屬性值、values[1]對應的是textBox2.Text屬性值、values[2]對應的是textBox3.Text屬性值、values[3]對應的是textBox4.Text屬性值。
責任編輯:admin

分享到:

作者: 武漢北大青鳥 原載: 武漢北大青鳥徐東校區 www.gaidft.icu
版權所有,轉載時必須以鏈接形式注明作者和原始出處及本聲明

027-87660036

開班信息

只為了方便您就學 徐東校區

武漢市洪山區友誼大道504號金馬凱旋家居北大青鳥徐東校區2樓(地鐵8號線徐東站D出口徐東平價旁)

全真項目實戰 入學簽就業協議

Copyright (c) 2006-2020 武漢宏鵬職業培訓學校 版權所有 All Rights Reserved.

在線咨詢