八、 提供可交互的屬性視圖
當你在visual c# .net中創(chuàng)建一個項目的時候,你可能會注意到屬性窗口的工具欄上有一個像閃電的按鈕,按下這個按鈕屬性窗口就會切換到事件視圖,這樣就可以來編輯事件處理了。
屬性窗口的視圖來自“屬性頁(property tabs)”,因此視圖使用的最主要的類是propertytab,命名空間是system.windows.forms.design。一個屬性頁可以和一個特別的組件、設計文檔關聯(lián)起來,或者是可以使用的靜態(tài)關聯(lián)。和組件或文檔關聯(lián)起來的屬性頁在類上用propertytabattribute特性來指定。這個特性指定要創(chuàng)建的tab的類型,它在屬性窗口上是否顯示由propertytabattribute的propertytabscope參數(shù)來指定。指定為component范圍的屬性頁的可見性由有propertytabattribute特性的組件的可見性來決定。document范圍的屬性頁則可以在當前項目的設計中都可見。他的默認值是propertytabscope.component。
舉一個例子來說,看看“funkybutton”項目。funkybutton是一個擴展了propertytab的usercontrol,而且可以讓我們把控件定為不規(guī)則的多邊形。
圖6. funkybutton
當前選擇的屬性頁就是屬性窗口從被選擇的控件的屬性中得到的。屬性頁因此就允許來操縱顯示屬性的不同集合。events頁就是像屬性一樣以某種方式來處理事件。在這個例子中,屬性頁就創(chuàng)建了表示控件頂點的屬性。
.net framework中的屬性用propertydescriptor類來封裝。propertydescriptor本身是一個抽象類,framework中由他派生的類提供了訪問組件的開放屬性的方法。不過,屬性窗口是直接作用在propertydescriptor上,而不是直接作用在屬性上。因此,我們就可以寫自己的propertydescriptor來做一些特殊的工作。在這個例子里,我們就有一個屬性表示控件的頂點數(shù),另一個就表示每一個頂點。再次注意一下,我們在屬性窗口上增加頁并不相應的作用在其他對象上。
當屬性窗口向propertytab詢問properties的時候,它就調(diào)用getproperties方法。對于我們的示例程序,這個方法就像下面的一樣:
public override propertydescriptorcollection
getproperties(itypedescriptorcontext context, object component,
attribute[] attrs)
{
// our list of props.
//
arraylist proplist = new arraylist();
// add the property for our count of vertices
//
proplist.add(new numpointspropertydescriptor(this));
// add a property descriptor for each vertex
//
for (inti = 0; i < ((funkybutton)component).points.count; i++)
{
proplist.add(new vertexpropertydescriptor(this,i));
}
// return the collection of propertydescriptors.
propertydescriptor[] props =
(propertydescriptor[])proplist.toarray(typeof(propertydescriptor));
return new propertydescriptorcollection(props);
}
getproperties僅僅是返回一些屬性描述的集合。propertydescriptors是相當?shù)暮唵危屑毑榭催@些代碼以了解他們是怎么工作的。
funkybutton同時示例了下拉列表編輯器的實現(xiàn)。對于每一個點,我們不是簡單的輸入坐標的x和y值,我們會圖示funkybutton的形狀,而且可以用圖形化的方法改變點的位置。這樣設置的編輯樣式更加地友好。
圖7. 圖形化的點向量
由于訂制的propertytab提供了屬性,重載這個屬性的編輯器也是很容易的。只要簡單地重載propertydescriptor的geteditor方法,然后返回訂制組件的實例就可以了。
public override object geteditor(type editorbasetype)
{
// make sure we're looking for a uitypeeditor.
//
if (editorbasetype == typeof(system.drawing.design.uitypeeditor))
{
// create and return one of our editors.
//
if (editor == null)
{
editor = new pointuieditor(owner.target);
}
return editor;
}
return base.geteditor(editorbasetype);
}
設計編輯器同樣簡單。編輯器就是一個簡單的usercontrol,所以我們就可以像設計其他的windowsforms對象一樣來做。
圖8. designing the editor
最后,當用戶在屬性窗口中點擊下拉箭頭時,我們的編輯器就可以將剛才創(chuàng)建ui編輯器彈出來了。pointuieditor中的uitypeeditor.editvalue重載后就可以實現(xiàn)了。
public override object editvalue(
itypedescriptorcontext context,
iserviceprovider sp, object value)
{
// get the editor service.
iwindowsformseditorservice edsvc =
(iwindowsformseditorservice)sp.getservice(typeof(iwindowsformseditorservice));
// create our ui
if (ui == null)
{
ui = new pointeditorcontrol();
}
// initialize the ui with the settings for this vertex
ui.selectedpoint = (point)value;
ui.editorservice = edsvc;
ui.target = (funkybutton)context.instance;
// instruct the editor service to display the control as a
// dropdown.
edsvc.dropdowncontrol(ui);
// return the updated value;
return ui.selectedpoint;
}
九、 我們同樣可以使用它
在你自己的應用中可以擁有和ide屬性窗一樣的特性。把system.windows.forms.propertygrid的控件,添加到ide中的toolbox中,通過獲取在toolbox的component標簽里的propertygrid。
propertygrid和其他的控件工作是一樣的。你可以anchor或者是dock他,改變它的色彩等。下面的列表列出了propertygrid的一些有趣的屬性。
•selectedobject
propertygrid要顯示的對象
•toolbarvisible
顯示或者隱藏propertygrid頂端的toolbar
•helpvisible
顯示或者隱藏propertygrid底端的幫助文本
•propertysort
設置propertygrid的排序類型 (categorized, alphabetical, etc.).
這些屬性都可以在設計時設置。在運行時,可以操作propertygrid讓他顯示的你的對象。下面是顯示一個button的例子。在這個例子中,porpertygrid的幫助和toolbox都被隱藏了。就像上面提到的,你可以設置他自己的屬性。
圖9. 隱藏了toolbar和幫助信息的propertygrid
十、 結論
net framework和visual studio .net給屬性窗口增加了相當多的功能。由于屬性窗口是rad的核心,這些特性可以在保持易用性的同時有很多的擴展,也因此在visual basic中用的很普遍。就像可以在我們的程序中使用propertygrid,我們可以把更多的時間放在如何寫好程序上,從而簡化我們的ui工作。
-----------------------------------------------------------------------------------------
<<<<<<<<<<<<<<<<<<<待續(xù)>>>>>>>>>>>>>>>>>>>>>>
新聞熱點
疑難解答
圖片精選