WPF資料繫結概觀(二)---使用ValueConverter

  • 4416
  • 0
  • WPF
  • 2012-05-01

WPF資料繫結概觀(二)---使用ValueConverter

上一篇文章講到了一個簡單的控制項屬性繫結的做法,直接將繫結目標屬性的值直接傳給繫結目標的屬性並不一定很適用,例如上一篇文章中直接將ProgressBar的Value直接在TextBlock裡顯示,一般的做法上或許會另外在這個TextBlock的前後再加入其它的TextBlock,將整個顯示的結果變成TextBlock(目前進度)+(繫結來源的Value)+TextBlock(%),這樣的佈置同樣可以達到將單純的ProgressBar.Value以一串字串顯示的效果,但是別忘了,一般的進度顯示是以0~1的double值來顯示,因此我們常會碰到的ProgressBar的Maximum會是1,而Minimum則會是0,如果你是將取得的值轉換成百分比再丟入ProgressBar.Value,這當然就沒有顯示的問題!不過如果是以一連串的資料繫結來做,例如將ProgressBar.Value繫結至某個類別的下載進度,再將TextBlock.Text繫結至ProgressBar.Value,在這連續的繫結中我們勢必在這兩個繫結的過程裡進行資料的換算!

一個方式是在下載進度繫結至ProgressBar.Value時將進度值*100,另一個方式則是在TextBlock繫結至ProgressBar.Value時再進行換算,這兩種方式都可以,而在資料繫結的過程中要進行數值換算

System.Windows.Threading.DispatcherTimer _timer = new System.Windows.Threading.DispatcherTimer();
       private void Button_Click(object sender, RoutedEventArgs e)
       {
           progressBar.Maximum = 1;
           progressBar.Minimum = 0;
           progressBar.Value = 0;

           Binding pbBinding = new Binding();
           pbBinding.Source = progressBar;
           pbBinding.Path = new PropertyPath(ProgressBar.ValueProperty);
           tbValue.SetBinding(TextBlock.TextProperty, pbBinding);           
           _timer.Interval = new TimeSpan(0, 0, 1);
           _timer.Tick += new EventHandler(_timer_Tick);
           _timer.Start();
       }
       void _timer_Tick(object sender, EventArgs e)
       {
           if (progressBar.Value < 1)
           {
               progressBar.Value += 0.01;
           }

           else
           {
               _timer.Stop();
           }
       }

我將原本的程式加入初始值並進行一些修改,讓它更符合實際的狀況,從上面的程式可以知道,每秒會讓ProgressBar.Value的值+0.01,這個時候TextBlock顯示的值必定是介於0~1,我們可以試著將這0~1的值轉換成百分比,首先我們先建立一個新的類別,我將這個類別命名為ValueConveryter:

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

namespace PropertyBinding
{
    class ValueConverter:IValueConverter
    {
        #region IValueConverter 成員

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {           
            string pbValueString = ((double)value*100).ToString();
            return "目前進度" + pbValueString + "%";

        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

這個類別必須實作System.Windows.Data.IValueConverter介面,而IValueConverter 只有兩個成員,Converter與ConverterBack,Converter用於來源屬性值流向目標屬性值;而ConverterBack則是用於雙向繫結,也就是目標屬性值回傳至來源屬性值時的轉換,不過在這個例子裡我們只實作Converter成員,紅色字的部分就是我們新增的程式碼,很簡單的程式,我想不必再多說明什麼了吧?而使用ValueConverter時只要將Binding物件的Converter屬性指定為我們新建的ValueConverter類別即可,如下面紅字部分:

System.Windows.Threading.DispatcherTimer _timer = new System.Windows.Threading.DispatcherTimer();
       private void Button_Click(object sender, RoutedEventArgs e)
       {
           progressBar.Maximum = 1;
           progressBar.Minimum = 0;
           progressBar.Value = 0;
           Binding pbBinding = new Binding();
           pbBinding.Source = progressBar;
           pbBinding.Path = new PropertyPath(ProgressBar.ValueProperty);

           pbBinding.Converter = new ValueConverter();
           tbValue.SetBinding(TextBlock.TextProperty, pbBinding);           
           _timer.Interval = new TimeSpan(0, 0, 1);
           _timer.Tick += new EventHandler(_timer_Tick);
           _timer.Start();
       }
       void _timer_Tick(object sender, EventArgs e)
       {
           if (progressBar.Value < 1)
           {
               progressBar.Value += 0.01;
           }
           else
           {
               _timer.Stop();
           }
       }

6

如此一來我們就可以順利地將double值轉換為百分比,並以我們想要的字串輸出!