首頁 » C#開發 » [C#] 自訂物件實作 TypeConverter 並與 UI 綁定

[C#] 自訂物件實作 TypeConverter 並與 UI 綁定

作者:

分類:

自訂類別的結繫問題

C# Winform提供很多方便的控件(Control)可讓開發人員拉出想要的介面,再使用資料結繫將介面與資料連結,就可以很輕鬆的做出一支視窗程式。

如果結繫得是.Net內建的物件(如Point、Size…等),就可以正常運作,但結繫方面如果是自定義的物件,就會遇到下面的狀況。

自訂類別

舉個例子,下面的類別Item裡面有各種ID資料,並放在Person內。

class Person
{
    public int Age { get; set; } = 0;
    public string Name { get; set; } = "Name";
    public Item Item { get; set; } = new Item();
}

class Item
{
    public int ID1 { get; set; } = 0;
    public int ID2 { get; set; } = 0;
    public int ID3 { get; set; } = 0;

    public Item() { }

    public Item(int id1, int id2, int id3)
    {
        ID1 = id1; ID2 = id2; ID3 = id3;
    }
}

當結繫Person到DataGridView上就會發現,物件顯示資訊只會是類別名稱,不是自己想要的內容。下面有兩種方法可以解決

方法一、覆寫 ToString()

此方法只能用於唯讀

可以透過覆寫ToString()就能顯示資料,如下圖可以正常顯示0:0:0,但會遇到個小問題。

public override string ToString()
{
    return $"{ID1}:{ID2}:{ID3}";
}

如果想要在DataGridView上編輯資料將Item改為0:0:11會引發錯誤,“從System.String”至”XXX.Item”的轉換無效”

因為表單不能將0:0:11轉換成Item的結構,於是需要實作TypeConverter給Item,讓手動輸入的資料可以轉換成類別。

方法二、實作 TypeConverter

*TypeConverter 類別定義
會提供轉換實值型別為其他型別,以及存取標準值和子屬性的統一方式。

TypeConverter是.Net用來提供給物件轉換使用,介面上看的到的輸入方式(Point, Size…etc)其實.Net內部都有實作對應的轉換器。

實作方式如下,需要建立類別ItemTypeConverter並繼承TypeConverter,如果按照官方建議需要實作覆寫下面四個方法

  • CanConvertFrom(ITypeDescriptorContext, Type)
  • CanConvertTo(ITypeDescriptorContext, Type)
  • ConvertFrom(ITypeDescriptorContext, CultureInfo, Object)
  • ConvertTo(ITypeDescriptorContext, CultureInfo, Object, Type)

但因為這篇只有用在介面結繫,結繫的顯示目標只有string,就沒有覆寫CanConvertTo()方法。

如果要讓DataGridView可以編輯自訂類別Item,也就是要實作CanConvertFrom()ConvertFrom()讓程式知道如何從輸入的字串轉換成對應的實例。

反之,ConvertTo()用來將物件轉換成對應的字串來顯示。在本篇與ToString()的作用類似。


class ItemTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(string))
        {
            return true;
        }
        return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string s)
        {
            try
            {
                var items = s.Split(':');
                return new Item(int.Parse(items[0]), int.Parse(items[1]), int.Parse(items[2]));
            }
            catch (Exception)
            {
                throw;
            }
        }
        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string))
        {
            var item = value as Item;
            return $"{item.ID1}:{item.ID2}:{item.ID3}";
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

最後在Item上加上TypeConverter的Attritube即可。

[TypeConverter(typeof(ItemTypeConverter))]
class Item
{
    ...略
}

現在簡單的小程式已經可以編輯Item的項目了,只要照著自訂的格式輸入程式就換進行轉換。

結語

實作TypeConverter做為類別之間的轉換器,自己常用來顯示自訂的資料項目,尤其是一些系統設定參數,可以讓介面看起來比較直觀,也符合物件導向的概念。

目前TypeConverter小弟只用了其中四個方法,其他還能更特殊更深入的應用,如果未來有遇到會在分享上來。

參考資料

「cian」的個人頭像

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *