在我們的專案中資料庫中所有的bool值都是用Char(1)來記錄的,‘T‘為真 `F’則為假。有意思的是DataGridView上的CheckBoxColumn有TrueValue和FalseValue屬性,如果你想用三態還有一個Indeterminate屬性。這樣只需要將TrueValue設定為’T’將FalseValue設定為‘F’就可以輕鬆繫結。但是CheckBox控制元件就沒有這些屬性,只能通過能隱式轉換為bool值的屬性繫結(bool型別,字串“True”和”False”),否則丟擲不是有效的布林值的異常。那麼如何將’T’轉化為true將’F’轉化為false來繫結到CheckBox上呢?

方法一、在Business類上加bool型的屬性,或建VO類。將原有屬性封裝為bool型。這種方法可行。但是需要一定的工作量,而且在類中加入一些重複的屬性(只是型別不同)感覺不爽。

方法二、使用Binding的Format和Parse事件。這個是我推薦的方法,其實微軟已經想到了繫結屬性與被繫結屬性可能要存在型別轉換的問題,這兩個事件就是為這種情況而預留的介面。

關於這兩個事件的官方文件可以參考:http://msdn.microsoft.com/zh-cn/library/system.windows.forms.binding.parse.aspx

Format是控制元件繫結時和資料來源的值發生變化時呼叫,Parse是離開焦點時呼叫。其實Parse掉用時就是改變資料來源時,因此Parse呼叫完就會呼叫Format.

Format顧名思義就是轉化為可以顯示的值,那麼CheckBox就是用bool值顯示。在我這個情況中就是由string轉化為bool。Parse就是解析為資料來源的所需要的值,在我這個情況就是由bool轉化為string。但是考慮到三態的可能因此我並不是進行string與bool的轉化。而是string與CheckState的轉化。

/// <summary>
/// Binds the CheckBox
/// </summary>
/// <param name="source">Binding Source</param>
/// <param name="checkBox">The Combo Box</param>
/// <param name="bindingField">The binding field name</param>
protected void BindingCheckBox(BindingSource source, CheckBox checkBox, string bindingField)
{
    Binding binding = checkBox.DataBindings["CheckState"];
    if (binding != null)
    {
        checkBox.DataBindings.Remove(binding);
    }
    Binding checkBoxBinding = new Binding("CheckState", source, bindingField, true, DataSourceUpdateMode.OnPropertyChanged);
    checkBoxBinding.Format += BindingCheckBox_Format;
    checkBoxBinding.Parse += BindingCheckBox_Parse;
    checkBox.DataBindings.Add(checkBoxBinding);
}
/// <summary>
/// Format event for checkBox binding
/// </summary>
/// <param name="sender">The source of the event. Here is Binding.</param>
/// <param name="e">Provides data for the System.Windows.Forms.Binding.Format and System.Windows.Forms.Binding.Parse events.</param>
void BindingCheckBox_Format(object sender, ConvertEventArgs e)
{
    if (e.DesiredType == typeof(CheckState))
    {
        if (e.Value != null && e.Value.ToString() == "T")
        {
            e.Value = CheckState.Checked;
        }
        else if (e.Value != null && e.Value.ToString() == "M")
        {
            e.Value = CheckState.Indeterminate;
        }
        else
        {
            e.Value = CheckState.Unchecked;
        }
    }
}
/// <summary>
/// Parse event for checkBox binding
/// </summary>
/// <param name="sender">The source of the event. Here is Binding.</param>
/// <param name="e">Provides data for the System.Windows.Forms.Binding.Format and System.Windows.Forms.Binding.Parse events.</param>
void BindingCheckBox_Parse(object sender, ConvertEventArgs e)
{
    if (e.DesiredType == typeof(string))
    {
        switch ((CheckState)e.Value)
        {
            case CheckState.Checked:
                e.Value = "T";
                break;
            case CheckState.Indeterminate:
                e.Value = "M";
                break;
            default:
                e.Value = "F";
                break;
        }
    }
}

這樣我們就可以使用這個方法來將CheckBox與繫結源進行繫結了。當然你的繫結源也可以是一般的物件。在這裡”M”來做不確定值,這是專案的約定。這裡我省去了判斷CheckBox是否是允許三態,而是判斷繫結的值是否是不確定態,如果是不確定態則認為CheckBox就是允許三態,否則非真即假。