編寫與.NET屬性窗口交互的RAD組件(四)
2024-07-10 13:03:52
供稿:網友
七、 編寫和顯示訂制的類型
屬性窗口中的編輯有如下三種工作方式:一,有些場合可以作為字符串來編輯,然后由typeconverter來實現類型的轉換。二,可以顯示一個下拉列表來選擇值。三,一個省略按鈕提供其他的ui界面來編輯值,比如filedialog和fontpicker。我們已經講過了字符串形式,接著我們就來看下拉列表。
.net framework已經包含了好幾種下拉列表的例子,如color,accessiblerole,dock等屬性。我們從下圖可以看到下拉列表的具體實現。
圖4. 下拉列表編輯器
實現下拉的工作同樣是由typeconverter來定義。如果看typeconverter的說明,可以看到有三個虛函數來實現這個功能:getstandardvaluessupported(),getstandardvalues()和getstandardvaluesexclusive()。重載這些方法,我們可以為屬性提供預先定義好的值列表。實際上,是typeconverter實現了下拉列表中的枚舉值。屬性窗口自己本身并沒有代碼來處理這種下拉列表的編輯,而僅僅是使用typeconverter的方法。
舉個例來說,我們有一個包含relation屬性的familymember組件,允許用戶選擇與其他人之間的關系。如果要使設計時界面更友好的話,屬性窗口應該使用下拉列表來提供一些常用值的選擇:如mother,father,daughter和sister等。除了提供的常用值之外,組件使用者也可以輸入其他的表示關系的字符串值。
public class familymember : component
{
private string relation = "unknown";
[typeconverter(typeof(relationconverter)),category("details")]
public string relation
{
get { return relation;}
set { this.relation = value;}
}
}
internal class relationconverter : stringconverter
{
private static standardvaluescollection defaultrelations =
new standardvaluescollection(
new string[]{"mother", "father", "sister",
"brother", "daughter", "son",
"aunt", "uncle", "cousin"});
public override bool getstandardvaluessupported(
itypedescriptorcontext context)
{
return true;
}
public override bool getstandardvaluesexclusive(
itypedescriptorcontext context)
{
// returning false here means the property will
// have a drop down and a value that can be manually
// entered.
return false;
}
public override standardvaluescollection getstandardvalues(
itypedescriptorcontext context)
{
return defaultrelations;
}
}
不過如何做一個更加定制化的ui呢?我們可以使用uitypeeditor類。uitypeeditor類包括了在顯示屬性或者是編輯屬性(比如下拉列表和省略按鈕)時可以由屬性窗口調用的方法。
一些類似于image,color,font.name的屬性類型會在屬性值的左邊有一個小的圖形化表示,這是通過重載uitypeeditor的paintvalue方法實現的。當屬性窗口得到定義了編輯器的屬性值的時候,它就提供給編輯器一個矩形框對象(rectangle)和畫圖的對象(graphic),他們都包含在paintvalue方法的事件參數paintvalueeventargs中。舉個例子來說,我們有一個grade類需要有圖形化的表示。下面就是我們的grade類。
[editor(typeof(gradeeditor), typeof(system.drawing.design.uitypeeditor))]
[typeconverter(typeof(gradeconverter))]
public struct grade
{
private int grade;
public grade(int grade)
{
this.grade = grade;
}
public int value
{
get
{
return grade;
}
}
}
當我們輸入一個年齡的時候,我們可以看到左邊的一個圖形表示。
圖5. 輸入年齡
實現它并不困難。注意到賦給grade類的editorattribute特性,它就是下面的這個類:
public class gradeeditor : uitypeeditor
{
public override bool getpaintvaluesupported(
itypedescriptorcontext context)
{
// let the property browser know we'd like
// to do custom painting.
return true;
}
public override void paintvalue(paintvalueeventargs pe)
{
// choose the right bitmap based on the value
string bmpname = null;
grade g = (grade)pe.value;
if (g.value > 80)
{
bmpname = "best.bmp";
}
else if (g.value > 60)
{
bmpname = "ok.bmp";
}
else
{
bmpname = "bad.bmp";
}
// draw that bitmap onto the surface provided.
bitmap b = new bitmap(typeof(gradeeditor), bmpname);
pe.graphics.drawimage(b, pe.bounds);
b.dispose();
}
}
像我們上面提到的,uitypeeditor可以實現屬性的下拉選擇和彈出對話框選擇。后面的例子會包括這樣的代碼。如果想知道進一步的信息的話,就要參考uitypeeditor.geteditstyle和uitypeeditor.editvalue方法以及iwindowsformseditorservice接口。
-----------------------------------
<<<<<<<<<<<<待續>>>>>>>>>>>>
國內最大的酷站演示中心!