充分利用 .net 框架的 propertygrid 控件
mark rideout
microsoft corporation
摘要:本文旨在幫助您了解 microsoft .net 框架中的 propertygrid 控件,以及如何針對您的應用程序自定義該控件。
適用于:
microsoft® .net® 框架
microsoft® visual studio® .net
目錄
propertygrid 控件簡介
創建 propertygrid 控件
何處使用 propertygrid 控件
選擇對象
自定義 propertygrid 控件
顯示復雜屬性
為屬性提供自定義 ui
小結
propertygrid 控件簡介
如果您使用過 microsoft® visual basic® 或 microsoft visual studio .net,那么您一定使用過屬性瀏覽器來瀏覽、查看和編輯一個或多個對象的屬性。.net 框架 propertygrid 控件是 visual studio .net 屬性瀏覽器的核心。propertygrid 控件顯示對象或類型的屬性,并主要通過使用反射來檢索項目的屬性。(反射是在運行時提供類型信息的技術。)
下面的屏幕快照顯示了 propertygrid 在窗體上的外觀。
圖 1:窗體上的 propertygrid
propertygrid 包含以下部分:
屬性
可展開屬性
屬性類別標題
屬性說明
屬性編輯器
屬性選項卡
命令窗格(顯示控件設計器提供的設計器操作)
創建 propertygrid 控件
要使用 visual studio .net 創建 propertygrid 控件,需要將該控件添加到工具箱中,因為默認情況下并不包含該控件。在 tools(工具)菜單中,選擇 customize toolbox(自定義工具箱)。在對話框中選擇 framework components(框架組件)選項卡,然后選擇 propertygrid。
如果您從命令行編譯代碼,請使用 /reference 選項并指定 system.windows.forms.dll。
以下代碼顯示了如何創建 propertygrid 控件并將其添加到窗體中。
' visual basic
imports system
imports system.drawing
imports system.componentmodel
imports system.windows.forms
imports system.globalization
public class optionsdialog
inherits system.windows.forms.form
private optionspropertygrid as system.windows.forms.propertygrid
public sub new()
mybase.new()
optionspropertygrid = new propertygrid()
optionspropertygrid.size = new size(300, 250)
me.controls.add(optionspropertygrid)
me.text = "選項對話框"
end sub
end class
//c#
using system;
using system.drawing;
using system.componentmodel;
using system.windows.forms;
using system.globalization;
public class optionsdialog : system.windows.forms.form
{
private system.windows.forms.propertygrid optionspropertygrid;
public optionsdialog()
{
optionspropertygrid = new propertygrid();
optionspropertygrid.size = new size(300, 250);
this.controls.add(optionspropertygrid);
this.text = "選項對話框";
}
[stathread]
static void main()
{
application.run(new optionsdialog());
}
}
何處使用 propertygrid 控件
在應用程序中的很多地方,您都可以使用戶與 propertygrid 進行交互,從而獲得更豐富的編輯體驗。例如,某個應用程序包含多個用戶可以設置的“設置”或選項,其中一些可能十分復雜。您可以使用單選按鈕、組合框或文本框來表示這些選項。但本文將逐步介紹如何使用 propertygrid 控件創建選項窗口來設置應用程序選項。上面所創建的 optionsdialog 窗體即是選項窗口的開始。現在,我們創建一個名為 appsettings 的類,其中包含映射到應用程序設置的所有屬性。如果創建單獨的類而不使用多個分散的變量,設置將更便于管理和維護。
' visual basic
public class appsettings
private _saveonclose as boolean = true
private _greetingtext as string = "歡迎使用應用程序!"
private _maxrepeatrate as integer = 10
private _itemsinmru as integer = 4
private _settingschanged as boolean = false
private _appversion as string = "1.0"
public property saveonclose() as boolean
get
return _saveonclose
end get
set(byval value as boolean)
saveonclose = value
end set
end property
public property greetingtext() as string
get
return _greetingtext
end get
set(byval value as string)
_greetingtext = value
end set
end property
public property itemsinmrulist() as integer
get
return _itemsinmru
end get
set(byval value as integer)
_itemsinmru = value
end set
end property
public property maxrepeatrate() as integer
get
return _maxrepeatrate
end get
set(byval value as integer)
_maxrepeatrate = value
end set
end property
public property settingschanged() as boolean
get
return _settingschanged
end get
set(byval value as boolean)
_settingschanged = value
end set
end property
public property appversion() as string
get
return _appversion
end get
set(byval value as string)
_appversion = value
end set
end property
end class
//c#
public class appsettings{
private bool saveonclose = true;
private string greetingtext = "歡迎使用應用程序!";
private int itemsinmru = 4;
private int maxrepeatrate = 10;
private bool settingschanged = false;
private string appversion = "1.0";
public bool saveonclose
{
get { return saveonclose; }
set { saveonclose = value;}
}
public string greetingtext
{
get { return greetingtext; }
set { greetingtext = value; }
}
public int maxrepeatrate
{
get { return maxrepeatrate; }
set { maxrepeatrate = value; }
}
public int itemsinmrulist
{
get { return itemsinmru; }
set { itemsinmru = value; }
}
public bool settingschanged
{
get { return settingschanged; }
set { settingschanged = value; }
}
public string appversion
{
get { return appversion; }
set { appversion = value; }
}
}
選項窗口上的 propertygrid 將使用此類,因此請將類定義添加到應用程序項目中,在添加時可創建新文件或將其添加到現有窗體源代碼的下方。
選擇對象
要標識 propertygrid 顯示的內容,請將 propertygrid.selectedobject 屬性設置為一個對象實例。然后,propertygrid 將完成其余的工作。每次設置 selectedobject 時,propertygrid 都會刷新顯示的屬性。這提供了一種簡單的方法來強制刷新屬性,或在運行時切換對象。您還可以調用 propertygrid.refresh 方法來刷新屬性。
接下來,您需要更新 optionsdialog 構造函數中的代碼,以創建一個 appsettings 對象,并將其設置為 propertygrid.selectedobject 屬性的值。
' visual basic
public sub new()
mybase.new()
optionspropertygrid = new propertygrid()
optionspropertygrid.size = new size(300, 250)
me.controls.add(optionspropertygrid)
me.text = "選項對話框"
' 創建 appsettings 類并在 propertygrid 中顯示該類。
dim appset as appsettings = new appsettings()
optionspropertygrid.selectedobject = appset
end sub
//c#
public optionsdialog()
{
optionspropertygrid = new propertygrid();
optionspropertygrid.size = new size(300, 250);
this.controls.add(optionspropertygrid);
this.text = "選項對話框";
// 創建 appsettings 類并在 propertygrid 中顯示該類。
appsettings appset = new appsettings();
optionspropertygrid.selectedobject = appset;
}
編譯并運行該應用程序。下面的屏幕快照顯示了應用程序的外觀。
圖 2:propertygrid 中選定的 appsettings 類
自定義 propertygrid 控件
您可以修改 propertygrid 的某些外觀特征以滿足自己的需要。可以更改某些屬性的顯示方式,甚至選擇不顯示某些屬性。那么,如何對 propertygrid 進行自定義呢?
更改 propertygrid 的外觀特征
propertygrid 的許多外觀特征都可以自定義。下面列出了其中的一部分:
通過 helpbackcolor、helpforecolor 和 helpvisible 屬性可以更改背景顏色、更改字體顏色或隱藏說明窗格。
通過 toolbarvisible 屬性可以隱藏工具欄,通過 backcolor 屬性可以更改工具欄的顏色,通過 largebuttons 屬性可以顯示大工具欄按鈕。
使用 propertysort 屬性可以按字母順序對屬性進行排序和分類。
通過 backcolor 屬性可以更改拆分器的顏色。
通過 linecolor 屬性可以更改網格線和邊框。
本示例中的選項窗口不需要工具欄,因此可以將 toolbarvisible 設置為 false。其余屬性均保留默認設置。
更改屬性的顯示方式
要更改某些屬性的顯示方式,您可以對這些屬性應用不同的特性。特性是用于為類型、字段、方法和屬性等編程元素添加批注的聲明標記,在運行時可以使用反射對其進行檢索。下面列出了其中的一部分:
descriptionattribute - 設置顯示在屬性下方說明幫助窗格中的屬性文本。這是一種為活動屬性(即具有焦點的屬性)提供幫助文本的有效方法。可以將此特性應用于 maxrepeatrate 屬性。
categoryattribute - 設置屬性在網格中所屬的類別。當您需要將屬性按類別名稱分組時,此特性非常有用。如果沒有為屬性指定類別,該屬性將被分配給雜項類別。可以將此特性應用于所有屬性。
browsableattribute – 表示是否在網格中顯示屬性。此特性可用于在網格中隱藏屬性。默認情況下,公共屬性始終顯示在網格中。可以將此特性應用于 settingschanged 屬性。
readonlyattribute – 表示屬性是否為只讀。此特性可用于禁止在網格中編輯屬性。默認情況下,帶有 get 和 set 訪問函數的公共屬性在網格中是可以編輯的。可以將此特性應用于 appversion 屬性。
defaultvalueattribute – 表示屬性的默認值。如果希望為屬性提供默認值,然后確定該屬性值是否與默認值相同,則可使用此特性。可以將此特性應用于所有屬性。
defaultpropertyattribute – 表示類的默認屬性。在網格中選擇某個類時,將首先突出顯示該類的默認屬性。可以將此特性應用于 appsettings 類。
現在,我們將其中的一些特性應用于 appsettings 類,以更改屬性在 propertygrid 中的顯示方式。
' visual basic
<defaultpropertyattribute("saveonclose")> _
public class appsettings
private _saveonclose as boolean = true
private _greetingtext as string = "歡迎使用應用程序!"
private _maxrepeatrate as integer = 10
private _itemsinmru as integer = 4
private _settingschanged as boolean = false
private _appversion as string = "1.0"
<categoryattribute("文檔設置"), _
defaultvalueattribute(true)> _
public property saveonclose() as boolean
get
return _saveonclose
end get
set(byval value as boolean)
saveonclose = value
end set
end property
<categoryattribute("全局設置"), _
readonlyattribute(true), _
defaultvalueattribute("歡迎使用應用程序!")> _
public property greetingtext() as string
get
return _greetingtext
end get
set(byval value as string)
_greetingtext = value
end set
end property
<categoryattribute("全局設置"), _
defaultvalueattribute(4)> _
public property itemsinmrulist() as integer
get
return _itemsinmru
end get
set(byval value as integer)
_itemsinmru = value
end set
end property
<descriptionattribute("以毫秒表示的文本重復率。"), _
categoryattribute("全局設置"), _
defaultvalueattribute(10)> _
public property maxrepeatrate() as integer
get
return _maxrepeatrate
end get
set(byval value as integer)
_maxrepeatrate = value
end set
end property
<browsableattribute(false),
defaultvalueattribute(false)> _
public property settingschanged() as boolean
get
return _settingschanged
end get
set(byval value as boolean)
_settingschanged = value
end set
end property
<categoryattribute("版本"), _
defaultvalueattribute("1.0"), _
readonlyattribute(true)> _
public property appversion() as string
get
return _appversion
end get
set(byval value as string)
_appversion = value
end set
end property
end class
//c#
[defaultpropertyattribute("saveonclose")]
public class appsettings{
private bool saveonclose = true;
private string greetingtext = "歡迎使用應用程序!";
private int maxrepeatrate = 10;
private int itemsinmru = 4;
private bool settingschanged = false;
private string appversion = "1.0";
[categoryattribute("文檔設置"),
defaultvalueattribute(true)]
public bool saveonclose
{
get { return saveonclose; }
set { saveonclose = value;}
}
[categoryattribute("全局設置"),
readonlyattribute(true),
defaultvalueattribute("歡迎使用應用程序!")]
public string greetingtext
{
get { return greetingtext; }
set { greetingtext = value; }
}
[categoryattribute("全局設置"),
defaultvalueattribute(4)]
public int itemsinmrulist
{
get { return itemsinmru; }
set { itemsinmru = value; }
}
[descriptionattribute("以毫秒表示的文本重復率。"),
categoryattribute("全局設置"),
defaultvalueattribute(10)]
public int maxrepeatrate
{
get { return maxrepeatrate; }
set { maxrepeatrate = value; }
}
[browsableattribute(false),
defaultvalueattribute(false)]
public bool settingschanged
{
get { return settingschanged; }
set { settingschanged = value; }
}
[categoryattribute("版本"),
defaultvalueattribute("1.0"),
readonlyattribute(true)]
public string appversion
{
get { return appversion; }
set { appversion = value; }
}
}
將這些特性應用于 appsettings 類后,編譯并運行該應用程序。下面的屏幕快照顯示了應用程序的外觀。
圖 3:propertygrid 中顯示的帶有類別和默認值的屬性
使用此版本的選項窗口后,您會注意到以下幾點:
顯示窗口時,將首先突出顯示 saveonclose 屬性。
選中 maxrepeatrate 屬性時,說明幫助窗格中將顯示“以毫秒表示的文本重復率”。
saveonclose 屬性顯示在“文檔設置”類別下。其他屬性分別顯示在“全局設置”和“版本”類別下。
settingschanged 屬性將不再顯示。
appversion 屬性為只讀。只讀屬性以灰顯文本顯示。
如果 saveonclose 屬性包含的值不是 true,該值將以粗體顯示。propertygrid 使用粗體文本表示包含非默認值的屬性。
顯示復雜屬性
到現在為止,選項窗口顯示的都是簡單的類型,如整數、布爾值和字符串。那么,如何顯示更復雜的類型呢?如果應用程序需要跟蹤窗口大小、文檔字體或工具欄顏色等信息,該如何處理呢?.net 框架提供的某些數據類型具有特殊的顯示功能,能使這些類型在 propertygrid 中更具可用性。
對所提供類型的支持
首先,請更新 appsettings 類,為窗口大小(size 類型)、窗口字體(font 類型)和工具欄顏色(color 類型)添加新屬性。
' visual basic
<defaultpropertyattribute("saveonclose")> _
public class appsettings
private _saveonclose as boolean = true
private _greetingtext as string = "歡迎使用應用程序!"
private _maxrepeatrate as integer = 10
private _itemsinmru as integer = 4
private _settingschanged as boolean = false
private _appversion as string = "1.0"
private _windowsize as size = new size(100, 100)
private _windowfont as font = new font("宋體", 9, fontstyle.regular)
private _toolbarcolor as color = systemcolors.control
<categoryattribute("文檔設置"), _
defaultvalueattribute(true)> _
public property saveonclose() as boolean
get
return _saveonclose
end get
set(byval value as boolean)
saveonclose = value
end set
end property
<categoryattribute("文檔設置")> _
public property windowsize() as size
get
return _windowsize
end get
set(byval value as size)
_windowsize = value
end set
end property
<categoryattribute("文檔設置")> _
public property windowfont() as font
get
return _windowfont
end get
set(byval value as font)
_windowfont = value
end set
end property
<categoryattribute("全局設置")> _
public property toolbarcolor() as color
get
return _toolbarcolor
end get
set(byval value as color)
_toolbarcolor = value
end set
end property
<categoryattribute("全局設置"), _
readonlyattribute(true), _
defaultvalueattribute("歡迎使用應用程序!")> _
public property greetingtext() as string
get
return _greetingtext
end get
set(byval value as string)
_greetingtext = value
end set
end property
<categoryattribute("全局設置"), _
defaultvalueattribute(4)> _
public property itemsinmrulist() as integer
get
return _itemsinmru
end get
set(byval value as integer)
_itemsinmru = value
end set
end property
<descriptionattribute("以毫秒表示的文本重復率。"), _
categoryattribute("全局設置"), _
defaultvalueattribute(10)> _
public property maxrepeatrate() as integer
get
return _maxrepeatrate
end get
set(byval value as integer)
_maxrepeatrate = value
end set
end property
<browsableattribute(false),
defaultvalueattribute(false)> _
public property settingschanged() as boolean
get
return _settingschanged
end get
set(byval value as boolean)
_settingschanged = value
end set
end property
<categoryattribute("版本"), _
defaultvalueattribute("1.0"), _
readonlyattribute(true)> _
public property appversion() as string
get
return _appversion
end get
set(byval value as string)
_appversion = value
end set
end property
end class
//c#
[defaultpropertyattribute("saveonclose")]
public class appsettings{
private bool saveonclose = true;
private string greetingtext = "歡迎使用應用程序!";
private int maxrepeatrate = 10;
private int itemsinmru = 4;
private bool settingschanged = false;
private string appversion = "1.0";
private size windowsize = new size(100,100);
private font windowfont = new font("宋體", 9, fontstyle.regular);
private color toolbarcolor = systemcolors.control;
[categoryattribute("文檔設置"),
defaultvalueattribute(true)]
public bool saveonclose
{
get { return saveonclose; }
set { saveonclose = value;}
}
[categoryattribute("文檔設置")]
public size windowsize
{
get { return windowsize; }
set { windowsize = value;}
}
[categoryattribute("文檔設置")]
public font windowfont
{
get {return windowfont; }
set { windowfont = value;}
}
[categoryattribute("全局設置")]
public color toolbarcolor
{
get { return toolbarcolor; }
set { toolbarcolor = value; }
}
[categoryattribute("全局設置"),
readonlyattribute(true),
defaultvalueattribute("歡迎使用應用程序!")]
public string greetingtext
{
get { return greetingtext; }
set { greetingtext = value; }
}
[categoryattribute("全局設置"),
defaultvalueattribute(4)]
public int itemsinmrulist
{
get { return itemsinmru; }
set { itemsinmru = value; }
}
[descriptionattribute("以毫秒表示的文本重復率。"),
categoryattribute("全局設置"),
defaultvalueattribute(10)]
public int maxrepeatrate
{
get { return maxrepeatrate; }
set { maxrepeatrate = value; }
}
[browsableattribute(false),
defaultvalueattribute(false)]
public bool settingschanged
{
get { return settingschanged; }
set { settingschanged = value; }
}
[categoryattribute("版本"),
defaultvalueattribute("1.0"),
readonlyattribute(true)]
public string appversion
{
get { return appversion; }
set { appversion = value; }
}
}
下面的屏幕快照顯示了新屬性在 propertygrid 中的外觀。
圖 4:顯示在 propertygrid 中的 .net 框架數據類型
請注意,windowfont 屬性帶有一個省略號 (...) 按鈕,按下該按鈕將顯示字體選擇對話框。此外,還可以展開該屬性以顯示更多的 font 屬性。某些 font 屬性提供有關字體的值和詳細信息的下拉列表。您可以展開 windowsize 屬性以顯示 size 類型的更多屬性。最后,請注意,toolbarcolor 屬性包含一個選定顏色的樣本,以及一個用于選擇不同顏色的自定義下拉列表。對于這些以及其他數據類型,.net 框架提供了其他的類,可以使在 propertygrid 中的編輯更加容易。
對自定義類型的支持
現在,您需要在 appsettings 類中添加另外兩個屬性,即 defaultfilename 和 spellcheckoptions。 defaultfilename 屬性用于獲取或設置字符串;spellcheckoptions 屬性用于獲取或設置 spellingoptions 類的實例。
spellingoptions 類是一個新類,用于管理應用程序的拼寫檢查屬性。對于何時創建單獨的類以管理對象的屬性,并沒有嚴格的規定,而取決于您的整個類設計。將 spellingoptions 類定義添加到應用程序項目中 - 可以添加到新文件中,也可以添加到窗體源代碼的下方。
' visual basic
<descriptionattribute("展開以查看應用程序的拼寫選項。")> _
public class spellingoptions
private _spellcheckwhiletyping as boolean = true
private _spellcheckcaps as boolean = false
private _suggestcorrections as boolean = true
<defaultvalueattribute(true)> _
public property spellcheckwhiletyping() as boolean
get
return _spellcheckwhiletyping
end get
set(byval value as boolean)
_spellcheckwhiletyping = value
end set
end property
<defaultvalueattribute(false)> _
public property spellcheckcaps() as boolean
get
return _spellcheckcaps
end get
set(byval value as boolean)
_spellcheckcaps = value
end set
end property
<defaultvalueattribute(true)> _
public property suggestcorrections() as boolean
get
return _suggestcorrections
end get
set(byval value as boolean)
_suggestcorrections = value
end set
end property
end class
//c#
[descriptionattribute("展開以查看應用程序的拼寫選項。")]
public class spellingoptions{
private bool spellcheckwhiletyping = true;
private bool spellcheckcaps = false;
private bool suggestcorrections = true;
[defaultvalueattribute(true)]
public bool spellcheckwhiletyping
{
get { return spellcheckwhiletyping; }
set { spellcheckwhiletyping = value; }
}
[defaultvalueattribute(false)]
public bool spellcheckcaps
{
get { return spellcheckcaps; }
set { spellcheckcaps = value; }
}
[defaultvalueattribute(true)]
public bool suggestcorrections
{
get { return suggestcorrections; }
set { suggestcorrections = value; }
}
}
再次編譯并運行選項窗口應用程序。下面的屏幕快照顯示了應用程序的外觀。
圖 5:在 propertygrid 中顯示的不帶類型轉換器的自定義數據類型
請注意 spellcheckoptions 屬性的外觀。與 .net 框架類型不同,它不展開或顯示自定義的字符串表示。如果要在自己的復雜類型中提供與 .net 框架類型相同的編輯體驗,該如何處理呢?.net 框架類型使用 typeconverter 和 uitypeeditor 類提供大部分 propertygrid 編輯支持,您也可以使用這些類。
添加可展開屬性支持
要使 propertygrid 能夠展開 spellingoptions 屬性,您需要創建 typeconverter。typeconverter 提供了從一種類型轉換為另一種類型的方法。propertygrid 使用 typeconverter 將對象類型轉換為 string,并使用該 string 在網格中顯示對象值。在編輯過程中,typeconverter 會將 string 轉換回對象類型。.net 框架提供的 expandableobjectconverter 類可以簡化這一過程。
提供可展開對象支持
創建一個從 expandableobjectconverter 繼承而來的類。
' visual basic
public class spellingoptionsconverter
inherits expandableobjectconverter
end class
//c#
public class spellingoptionsconverter:expandableobjectconverter
{ }
如果 destinationtype 參數與使用此類型轉換器的類(示例中的 spellingoptions 類)的類型相同,則覆蓋 canconvertto 方法并返回 true;否則返回基類 canconvertto 方法的值。
' visual basic
public overloads overrides function canconvertto( _
byval context as itypedescriptorcontext, _
byval destinationtype as type) as boolean
if (destinationtype is gettype(spellingoptions)) then
return true
end if
return mybase.canconvertto(context, destinationtype)
end function
//c#
public override bool canconvertto(itypedescriptorcontext context,
system.type destinationtype)
{
if (destinationtype == typeof(spellingoptions))
return true;
return base.canconvertto(context, destinationtype);
}
覆蓋 convertto 方法,并確保 destinationtype 參數是一個 string,并且值的類型與使用此類型轉換器的類(示例中的 spellingoptions 類)相同。如果其中任一情況為 false,都將返回基類 convertto 方法的值;否則,返回值對象的字符串表示。字符串表示需要使用唯一分隔符將類的每個屬性隔開。由于整個字符串都將顯示在 propertygrid 中,因此需要選擇一個不會影響可讀性的分隔符,逗號的效果通常比較好。
' visual basic
public overloads overrides function convertto( _
byval context as itypedescriptorcontext, _
byval culture as cultureinfo, _
byval value as object, _
byval destinationtype as system.type) _
as object
if (destinationtype is gettype(system.string) _
andalso typeof value is spellingoptions) then
dim so as spellingoptions = ctype(value, spellingoptions)
return "在鍵入時檢查: " & so.spellcheckwhiletyping & _
",檢查大小寫: " & so.spellcheckcaps & _
",建議更正: " & so.suggestcorrections
end if
return mybase.convertto(context, culture, value, destinationtype)
end function
//c#
public override object convertto(itypedescriptorcontext context,
cultureinfo culture,
object value,
system.type destinationtype)
{
if (destinationtype == typeof(system.string) &&
value is spellingoptions){
spellingoptions so = (spellingoptions)value;
return "在鍵入時檢查:" + so.spellcheckwhiletyping +
",檢查大小寫: " + so.spellcheckcaps +
",建議更正: " + so.suggestcorrections;
}
return base.convertto(context, culture, value, destinationtype);
}
(可選)通過指定類型轉換器可以從字符串進行轉換,您可以啟用網格中對象字符串表示的編輯。要執行此操作,首先需要覆蓋 canconvertfrom 方法并返回 true(如果源 type 參數為 string 類型);否則,返回基類 canconvertfrom 方法的值。
' visual basic
public overloads overrides function canconvertfrom( _
byval context as itypedescriptorcontext, _
byval sourcetype as system.type) as boolean
if (sourcetype is gettype(string)) then
return true
end if
return mybase.canconvertfrom(context, sourcetype)
end function
//c#
public override bool canconvertfrom(itypedescriptorcontext context,
system.type sourcetype)
{
if (sourcetype == typeof(string))
return true;
return base.canconvertfrom(context, sourcetype);
}
要啟用對象基類的編輯,同樣需要覆蓋 convertfrom 方法并確保值參數是一個 string。如果不是 string,將返回基類 convertfrom 方法的值;否則,返回基于值參數的類(示例中的 spellingoptions 類)的新實例。您需要根據值參數解析類的每個屬性的值。了解在 convertto 方法中創建的分隔字符串的格式將有助于您的解析。
' visual basic
public overloads overrides function convertfrom( _
byval context as itypedescriptorcontext, _
byval culture as cultureinfo, _
byval value as object) as object
if (typeof value is string) then
try
dim s as string = cstr(value)
dim colon as integer = s.indexof(":")
dim comma as integer = s.indexof(",")
if (colon <> -1 andalso comma <> -1) then
dim checkwhiletyping as string = s.substring(colon + 1, _
(comma - colon - 1))
colon = s.indexof(":", comma + 1)
comma = s.indexof(",", comma + 1)
dim checkcaps as string = s.substring(colon + 1, _
(comma - colon - 1))
colon = s.indexof(":", comma + 1)
dim suggcorr as string = s.substring(colon + 1)
dim so as spellingoptions = new spellingoptions()
so.spellcheckwhiletyping = boolean.parse(checkwhiletyping)
so.spellcheckcaps = boolean.parse(checkcaps)
so.suggestcorrections = boolean.parse(suggcorr)
return so
end if
catch
throw new argumentexception( _
"無法將“" & cstr(value) & _
"”轉換為 spellingoptions 類型")
end try
end if
return mybase.convertfrom(context, culture, value)
end function
//c#
public override object convertfrom(itypedescriptorcontext context,
cultureinfo culture, object value)
{
if (value is string) {
try {
string s = (string) value;
int colon = s.indexof(':');
int comma = s.indexof(',');
if (colon != -1 && comma != -1) {
string checkwhiletyping = s.substring(colon + 1 ,
(comma - colon - 1));
colon = s.indexof(':', comma + 1);
comma = s.indexof(',', comma + 1);
string checkcaps = s.substring(colon + 1 ,
(comma - colon -1));
colon = s.indexof(':', comma + 1);
string suggcorr = s.substring(colon + 1);
spellingoptions so = new spellingoptions();
so.spellcheckwhiletyping =boolean.parse(checkwhiletyping);
so.spellcheckcaps = boolean.parse(checkcaps);
so.suggestcorrections = boolean.parse(suggcorr);
return so;
}
}
catch {
throw new argumentexception(
"無法將“" + (string)value +
"”轉換為 spellingoptions 類型");
}
}
return base.convertfrom(context, culture, value);
}
現在已經有了一個類型轉換器類,下面您需要確定使用該類的目標類。您可以通過將 typeconverterattribute 應用到目標類(示例中的 spellingoptions 類)來執行此操作。
' visual basic
' 應用于 spellingoptions 類的 typeconverter 特性。
<typeconverter(gettype(spellingoptionsconverter)), _
descriptionattribute("展開以查看應用程序的拼寫選項。")> _
public class spellingoptions
...
end class
//c#
// 應用于 spellingoptions 類的 typeconverter 特性。
[typeconverterattribute(typeof(spellingoptionsconverter)),
descriptionattribute("展開以查看應用程序的拼寫選項。")]
public class spellingoptions{ ... }
再次編譯并運行選項窗口應用程序。下面的屏幕快照顯示了選項窗口目前的外觀。
圖 6:在 propertygrid 中顯示的帶有類型轉換器的自定義數據類型
注意: 如果只需要可展開對象支持,而不需要自定義字符串表示,則只需將 typeconverterattribute 應用到類中。將 expandableobjectconverter 指定為類型轉換器類型。
添加域列表和簡單的下拉列表屬性支持
對于基于 enum 類型返回枚舉的屬性,propertygrid 會自動在下拉列表中顯示枚舉值。enumconverter 也提供了這一功能。對于自己的屬性,您可能希望為用戶提供一個有效值列表(有時也稱為選取列表或域列表),而其類型并不是基于 enum。如果域值在運行時之前未知,或者值可以更改,則屬于這種情況。
修改選項窗口,提供一個用戶可從中選擇的默認文件名的域列表。您已經將 defaultfilename 屬性添加到 appsettings 類。下一步是在 propertygrid 中顯示屬性的下拉列表,以提供域列表。
提供簡單的下拉列表屬性支持
創建一個從類型轉換器類繼承而來的類。由于 defaultfilename 屬性屬于 string 類型,因此可以從 stringconverter 中繼承。如果屬性類型的類型轉換器不存在,則可以從 typeconverter 繼承;這里并不需要。
' visual basic
public class filenameconverter
inherits stringconverter
end class
//c#
public class filenameconverter: stringconverter
{ }
覆蓋 getstandardvaluessupported 方法并返回 true,表示此對象支持可以從列表中選取的一組標準值。
' visual basic
public overloads overrides function getstandardvaluessupported( _
byval context as itypedescriptorcontext) as boolean
return true
end function
//c#
public override bool getstandardvaluessupported(
itypedescriptorcontext context)
{
return true;
}
覆蓋 getstandardvalues 方法并返回填充了標準值的 standardvaluescollection。創建 standardvaluescollection 的方法之一是在構造函數中提供一個值數組。對于選項窗口應用程序,您可以使用填充了建議的默認文件名的 string 數組。
' visual basic
public overloads overrides function getstandardvalues( _
byval context as itypedescriptorcontext) _
as standardvaluescollection
return new standardvaluescollection(new string() {"新文件", _
"文件1", _
"文檔1"})
end function
//c#
public override standardvaluescollection
getstandardvalues(itypedescriptorcontext context)
{
return new standardvaluescollection(new string[]{"新文件",
"文件1",
"文檔1"});
}
(可選)如果希望用戶能夠鍵入下拉列表中沒有包含的值,請覆蓋 getstandardvaluesexclusive 方法并返回 false。這從根本上將下拉列表樣式變成了組合框樣式。
' visual basic
public overloads overrides function getstandardvaluesexclusive( _
byval context as itypedescriptorcontext) as boolean
return false
end function
//c#
public override bool getstandardvaluesexclusive(
itypedescriptorcontext context)
{
return false;
}
擁有自己的用于顯示下拉列表的類型轉換器類后,您需要確定使用該類的目標。在本示例中,目標為 defaultfilename 屬性,因為類型轉換器是針對該屬性的。將 typeconverterattribute 應用到目標屬性中。
' visual basic
' 應用到 defaultfilename 屬性的 typeconverter 特性。
<typeconverter(gettype(filenameconverter)), _
categoryattribute("文檔設置")> _
public property defaultfilename() as string
get
return _defaultfilename
end get
set(byval value as string)
_defaultfilename = value
end set
end property
//c#
// 應用到 defaultfilename 屬性的 typeconverter 特性。
[typeconverter(typeof(filenameconverter)),
categoryattribute("文檔設置")]
public string defaultfilename
{
get{ return defaultfilename; }
set{ defaultfilename = value; }
}
再次編譯并運行選項窗口應用程序。下面的屏幕快照顯示了選項窗口目前的外觀。請注意 defaultfilename 屬性的外觀。
圖 7:在 propertygrid 中顯示下拉域列表
為屬性提供自定義 ui
如上所述,.net 框架類型使用 typeconverter 和 uitypeeditor 類(以及其他類)來提供 propertygrid 編輯支持。有關如何使用 typeconverter,請參閱對自定義類型的支持一節;您也可以使用 uitypeeditor 類來自定義 propertygrid。
您可以在 propertygrid 中提供小圖形表示和屬性值,類似于為 image 和 color 類提供的內容。要在自定義中執行此操作,請從 uitypeeditor 繼承,覆蓋 getpaintvaluesupported 并返回 true。然后,覆蓋 uitypeeditor.paintvalue 方法,并在自己的方法中使用 paintvalueeventargs.graphics 參數繪制圖形。最后,將 editor 特性應用到使用 uitypeeditor 類的類或屬性。
下面的屏幕快照顯示了結果外觀。
圖 8:在 propertygrid 中顯示屬性的自定義圖形
您也可以提供自己的下拉列表控件,這與 control.dock 屬性用來為用戶提供靠接選擇的控件類似。要執行此操作,請從 uitypeeditor 繼承,覆蓋 geteditstyle,然后返回一個 uitypeeditoreditstyle 枚舉值,例如 dropdown。您的自定義下拉列表控件必須從 control 或 control 的派生類(例如 usercontrol)繼承而來。然后,覆蓋 uitypeeditor.editvalue 方法。使用 iserviceprovider 參數調用 iserviceprovider.getservice 方法,以獲取一個 iwindowsformseditorservice 實例。最后,調用 iwindowsformseditorservice.dropdowncontrol 方法來顯示您的自定義下拉列表控件。請記住將 editor 特性應用到使用 uitypeeditor 類的類或屬性中。
下面的屏幕快照顯示了結果外觀。
圖 9:在 propertygrid 中顯示屬性的自定義下拉列表控件
除了使用 typeeditor 和 uitypeeditor 類外,還可以自定義 propertygrid 以顯示其他屬性選項卡。屬性選項卡從 propertytab 類繼承而來。如果您使用過 microsoft visual c#™ .net 中的屬性瀏覽器,那么就可能看到過自定義的 propertytab。events 選項卡(帶有閃電圖形的按鈕)就是一個自定義的 propertytab。下面的屏幕快照顯示了自定義 propertytab 的另一個示例。可以使用 propertytab 編輯按鈕的邊界點,以創建自定義的按鈕形狀。
圖 10:在 propertygrid 中顯示自定義選項卡
有關使用 uitypeeditor 類自定義 propertygrid 的詳細信息,以及上述自定義用戶界面代碼示例,請參閱 shawn burke 的文章 make your components really rad with visual studio .net property browser(英文)。
小結
.net 框架提供的 properygrid 控件具有豐富的編輯功能,您可以使用這些編輯功能來改善您的用戶界面。propertygrid 的自定義非常簡單,您可以在任何應用程序中使用這一控件。此外,由于 visual studio .net 屬性瀏覽器是建立在 propertygrid 的基礎之上的,因此您可以使用這些技術提供更豐富的設計時體驗。
中國最大的web開發資源網站及技術社區,