運(yùn)行時(shí)自定義PropertyGrid顯示屬性項(xiàng)目
簡述
在PropertyGrid所顯示的屬性內(nèi)容包括屬性分類(Category)及組件屬性,
在一般情況下直接使用PropertyGrid來顯示一個(gè)對(duì)象的所有屬性是非常方便的,只需一個(gè)語句就能完成:
propertyGrid.SelectedObject = component;
但在實(shí)際應(yīng)用中可能會(huì)不需要顯示所有屬性項(xiàng)目,而是通過外部指定(通過XML等進(jìn)行描述),這些設(shè)置一般情況下在創(chuàng)建組件時(shí)用代碼中的Attribute來進(jìn)行具體設(shè)置,如所屬分類,顯示標(biāo)題等,這只能針對(duì)于一些自建的組件可以這么做。
問題描述
像上面所說,在創(chuàng)建自建組件時(shí)可以用Attribute的方式來設(shè)置PropertyGrid的顯示樣式,但這種方法不能應(yīng)用于已有的組件,像系統(tǒng)中的TextBox,Button等,除非自己建立一個(gè)由這些組件派生的類,當(dāng)然這樣做會(huì)加大復(fù)雜度。像要實(shí)現(xiàn)下面所顯示的這種效果在實(shí)際操作時(shí)會(huì)很麻煩。
左圖是TextBox原有的所有屬性,右圖是經(jīng)過處理后的屬性
解決方法
在.Net中提供了一個(gè)自定義類型說明的接口(System.ComponentModel.ICustomTypeDescriptor),PropertyGrid可以直接自動(dòng)處理用此接口生成的對(duì)象,因此在處理這個(gè)問題的時(shí)候只需要?jiǎng)?chuàng)建一個(gè)基于這個(gè)接口的處理類就可以達(dá)到世期望的目標(biāo),在這個(gè)接口中提供了GetProperties方法用于返回所選組件的所有屬性,因此我們可以通過這個(gè)方法可以對(duì)我們所需要的屬性進(jìn)行過濾,下面是一段GetPropertys的處理代碼:
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
List<CustomPropertyDescriptor> tmpPDCLst = new List<CustomPropertyDescriptor>();
PropertyDescriptorCollection tmpPDC = TypeDescriptor.GetProperties(mCurrentSelectObject, attributes);
IEnumerator tmpIe = tmpPDC.GetEnumerator();
CustomPropertyDescriptor tmpCPD;
PropertyDescriptor tmpPD;
while (tmpIe.MoveNext())
{
tmpPD = tmpIe.Current as PropertyDescriptor;
if (mObjectAttribs.ContainsKey(tmpPD.Name))
{
tmpCPD = new CustomPropertyDescriptor(mCurrentSelectObject, tmpPD);
tmpCPD.SetDisplayName(mObjectAttribs[tmpPD.Name]);
//此處用于處理屬性分類的名稱,可以在XML等設(shè)置文件中進(jìn)行設(shè)置,在這段代碼中只是簡單的在分類后加了“中文”兩個(gè)字
tmpCPD.SetCategory(tmpPD.Category + "中文");
tmpPDCLst.Add(tmpCPD);
}
}
return new PropertyDescriptorCollection(tmpPDCLst.ToArray());
}
當(dāng)然在進(jìn)行屬性過慮之后,PropertyGrid中所顯示的屬性名稱都還是原有名稱,若想同時(shí)改變?cè)?/span>PropertyGrid中顯示出來的名稱則需要重寫PropertyDescriptor中的部分方法,在上面這段代碼中的CustomPropertyDescriptor就是一個(gè)基于PropertyDescriptor的類。
在CustomPropertyDescriptor類中最主要的是重寫DisplayName與Category這兩個(gè)屬性,但由于在PropertyDescriptor中這兩個(gè)屬性是只讀的,因此在這個(gè)類中需要加入兩個(gè)用于設(shè)置這兩個(gè)屬性的方法(或直接用Field)在這里我使用了SetDispalyName與SetCategory這兩個(gè)方法:
private string mCategory;
public override string Category
{
get { return mCategory; }
}
private string mDisplayName ;
public override string DisplayName
{
get { return mDisplayName; }
}
public void SetDisplayName(string pDispalyName)
{
mDisplayName = pDispalyName;
}
public void SetCategory(string pCategory)
{
mCategory = pCategory;
}
在寫ICustomTypeDescriptor接口時(shí),其他的一些方法可以用TypeDescriptor直接返回相關(guān)方法調(diào)用,并在GetPropertyOwner方法中應(yīng)返回當(dāng)前選擇對(duì)象否則將不會(huì)對(duì)修改值起任何作用
public object GetPropertyOwner(PropertyDescriptor pd)
{
}
//加載組件屬性,從XML文件載入,此處為Button
使用方法
XmlNode tmpXNode = mXDoc.SelectSingleNode("Components/Component[@Name=\"Button\"]");
//選擇屬性設(shè)置
XmlNodeList tmpXPropLst = tmpXNode.SelectNodes("Propertys/Property");
//創(chuàng)建CustomProperty對(duì)象
CustomProperty cp = new CustomProperty(sender, tmpXPropLst);
//設(shè)置PropertyGrid選擇對(duì)象
propertyGrid1.SelectedObject = cp;
文件下載
演示
聯(lián)系客服