一个关于PropertyGrid的问题,网上怎么都找不到答案,高人指点。
我做一个基于设计器IDesignerHost的程序,我想让DesignSu易做图ce.View上的控件在PropertyGrid中显示的属性为中文,于是我实现了ICustomTypeDescriptor接口MyCustomTypeDescriptor,但是有一个问题确实怎么也解决不了,那就是在属性中没有Name名字这一项,我查看了控件的基类Control,发现Name被定义为<Browsable(False)>,我在MyCustomTypeDescriptor中来修改Name的Browsable特性,可是结果还是一样。我发现除了把设计器中的控件直接传给PropertyGrid.SelectedObject以外,其他像把MyCustomTypeDescriptor实例或是在运行模式中把控件传递给PropertyGrid.SelectedObject,都不会有(Name)这一项,怎么做才能让他显示出来并且让Name可修改?请高手给予指点,先拜谢! --------------------编程问答-------------------- 自已定义一个字段用来显示中文称,在描述器中,让GRID显示这个字段的值即可,你继承了这个接口,里面有很多方法需要重写 --------------------编程问答-------------------- 参考下面的实现,可以自由展示类的元数据,看起来可以随意改变,其实是做了中间转换.
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Xml;
using Generator.Design.Common;
namespace Generator.Design.BLL
{
/// <summary>
/// 实现属性到PropertyGrid重现的重要类,必须根据实际需要来呈现
/// </summary>
public class PropertyBaseDescriptor:PropertyDescriptor
{
private Attribute[] m_attributes;
private PropertyBase m_pd;
private XmlDocument xmldoc = new XmlDocument();
public PropertyBaseDescriptor(PropertyBase t_pd, Attribute[] t_attributes)
: base(t_pd.Name, t_attributes)
{
m_pd = t_pd;
m_attributes = t_attributes;
}
public override bool CanResetValue(object component)
{
return false ;
}
public override object GetValue(object component)
{
return m_pd.Value;
}
public override void ResetValue(object component)
{
}
public override void SetValue(object component, object value)
{
m_pd.Value = value;
}
//重要属性,用来显示中文名称或自定义的值,我把中文名称放在一个XML文件里
public override string DisplayName
{
get
{
string t_name = m_pd.Name.Trim();
string t_path = Utility.GetRootPath() + "\\Config\\ChineseName.xml";
xmldoc.Load(t_path);
XmlNode node=null;
try
{
node = xmldoc.SelectSingleNode(string.Format("/NameList//NameString[@name=\"{0}\"]", t_name));
}
catch
{
node = null;
}
if (node != null)
{
t_name = node.InnerText;
}
return t_name ;
}
}
public override string Category
{
get
{
return m_pd.Category;
}
}
public override Type ComponentType
{
get { return m_pd.GetType(); }
}
public override bool IsReadOnly
{
get { return m_pd.IsReadOnly; }
}
public override Type PropertyType
{
get
{
if (m_pd.Value != null)
{
return m_pd.Value.GetType();
}
else
{
//有可能有问题,也就是说,如果值为空,将不能获取对象的属性类型
//不知有没有别的方法
return typeof(string);
}
}
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
public override bool IsBrowsable
{
get
{
return m_pd.IsBrowsable;
}
}
public override TypeConverter Converter
{
get
{
return m_pd.Converter;
}
}
public override object GetEditor(Type editorBaseType)
{
return m_pd.uiTypeConvertor;
}
}
}
--------------------编程问答-------------------- 下面的代码有二个作用,一是定义属性基类,二是定义属性基类集合,因为PROPERTYGRID显示的是属性类集合.
下面的方法中可以自由定义属性的显示与隐瞒,可以达到根据某个属性的值来决定是否显示其它属性的效果,包括只读或可写.
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms.Design;
using System.Drawing.Design;
namespace Generator.Design.BLL
{
/// <summary>
/// 对应类的一个属性,尽可能包括类属性所有的特点
/// </summary>
public class PropertyBase
{
private string m_Name;
private object m_Value;
private string m_Description;
private string m_Category;
private bool m_isReadOnly;
private bool m_IsBrowsable;
private Type m_type;
private TypeConverter m_Converter;
private UITypeEditor m_uiTypeEditor;
private List<Attribute> m_attrs=new List<Attribute>();
/// <summary>
/// 属性名
/// </summary>
public string Name
{
get
{
return m_Name;
}
set
{
m_Name = value;
}
}
/// <summary>
/// 属性值
/// </summary>
public object Value
{
get
{
return m_Value;
}
set
{
m_Value = value;
}
}
/// <summary>
/// 属性描述
/// </summary>
public string Description
{
get
{
return m_Description;
}
set
{
m_Description = value;
}
}
/// <summary>
/// 属性的特性
/// </summary>
public Attribute[] Attributes
{
get
{
Attribute[] t_atts = new Attribute[m_attrs.Count];
int iCount = m_attrs.Count;
for (int j = 0; j < iCount; j++)
{
t_atts[j] = m_attrs[j];
}
return t_atts;
}
}
/// <summary>
/// 属性所属分类
/// </summary>
public string Category
{
get
{
return m_Category;
}
set
{
m_Category = value;
}
}
/// <summary>
/// 是否只读
/// </summary>
public bool IsReadOnly
{
get
{
return m_isReadOnly;
}
set
{
m_isReadOnly = value;
}
}
/// <summary>
/// 是否显示
/// </summary>
public bool IsBrowsable
{
get
{
return m_IsBrowsable;
}
set
{
m_IsBrowsable = value;
}
}
/// <summary>
/// 属性类型
/// </summary>
public Type PropertyType
{
get
{
return m_type;
}
set
{
m_type = value;
}
}
/// <summary>
/// 属性的类型转换器
/// </summary>
public TypeConverter Converter
{
get
{
return m_Converter;
}
set
{
m_Converter = value;
}
}
/// <summary>
/// 属性指定的UI编辑器
/// </summary>
public UITypeEditor uiTypeConvertor
{
get
{
return m_uiTypeEditor;
}
set
{
m_uiTypeEditor = value;
}
}
/// <summary>
/// 给属性增加一个特性
/// </summary>
/// <param name="t_newatt"></param>
public void AddAttribute(Attribute t_newatt)
{
if (m_attrs.Count > 0)
{
foreach (Attribute t_att in m_attrs)
{
if (t_att.Match(t_newatt))
{
m_attrs.Remove(t_att);
}
}
}
m_attrs.Add(t_newatt);
}
/// <summary>
/// 删除属性的一个特性
/// </summary>
/// <param name="t_att"></param>
public void DeleteAttribute(Attribute t_att)
{
try
{
m_attrs.Remove(t_att);
}
catch { }
}
}
--------------------编程问答-------------------- /// <summary>
/// 对应类的所有属性,相当于上上一个类的集合,提供给PropertyGrid来显示
/// 因为是定制的,必须实现定制接口
/// </summary>
public class PropertyBaseCollection :ICustomTypeDescriptor
{
#region 实现功能(基于List<PropertyBase>)
/// <summary>
/// 类属性泛型集合变量
/// </summary>
private List<PropertyBase> m_propertys=new List<PropertyBase>();
/// <summary>
/// 新增一个属性
/// </summary>
/// <param name="t_property">属性类</param>
public void Add(PropertyBase t_property)
{
m_propertys.Add(t_property);
}
/// <summary>
/// 删除一个属性
/// </summary>
/// <param name="t_property">属性类</param>
public void Delete(PropertyBase t_property)
{
m_propertys.Remove(t_property);
}
/// <summary>
/// 删除一个属性
/// </summary>
/// <param name="t_PropertyName">属性名</param>
public void Delete(string t_PropertyName)
{
int i = m_propertys.Count;
PropertyBase t;
for (int j=0;j<i;j++)
{
t = m_propertys[j];
if (t.Name.Trim() == t_PropertyName.Trim())
{
m_propertys.Remove(t);
break;
}
}
}
/// <summary>
/// 根据属性名,设置只读特性
/// </summary>
/// <param name="t_PropertyName">属性名</param>
/// <param name="t_bl">布尔值</param>
/// <returns></returns>
public bool UpdateWriteRead(string t_PropertyName, bool t_bl)
{
bool t_ok = false;
try
{
int iCount = m_propertys.Count;
if (iCount > 0)
{
for (int i = 0; i < iCount; i++)
{
if (m_propertys[i].Name.Trim() == t_PropertyName.Trim())
{
m_propertys[i].IsReadOnly = t_bl;
t_ok = true;
break;
}
}
}
}
catch
{
t_ok = false;
}
return t_ok;
}
/// <summary>
/// 根据属性名,设置隐藏特性
/// </summary>
/// <param name="t_PropertyName">属性名</param>
/// <param name="t_bl">布尔值</param>
/// <returns></returns>
public bool HideProperty(string t_PropertyName, bool t_bl)
{
bool t_ok = false;
try
{
int iCount = m_propertys.Count;
if (iCount > 0)
{
for (int i = 0; i < iCount; i++)
{
if (m_propertys[i].Name.Trim() == t_PropertyName.Trim())
{
m_propertys[i].IsBrowsable = t_bl;
t_ok = true;
break;
}
}
}
}
catch
{
t_ok = false;
}
return t_ok;
}
/// <summary>
/// 类属性个数
/// </summary>
public int Count
{
get
{
return m_propertys.Count;
}
}
/// <summary>
/// 类属性索引器
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public PropertyBase this[int index]
{
get
{
return m_propertys[index];
}
}
public PropertyBase this[string t_PropertyName]
{
get
{
PropertyBase t_property = null;
int iCount = m_propertys.Count;
for (int i = 0; i < iCount; i++)
{
if (m_propertys[i].Name.Trim().ToLower() == t_PropertyName.Trim().ToLower())
{
t_property= m_propertys[i];
break;
}
}
return t_property;
}
}
#endregion
#region 以下部分是实现接口规范
/// <summary>
///
/// </summary>
/// <returns></returns>
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes(this, true);
}
public string GetClassName()
{
return TypeDescriptor.GetClassName(this,true);
}
public string GetComponentName()
{
return TypeDescriptor.GetComponentName(this, true);
}
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this, true);
}
public PropertyDescriptor GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(this, true);
}
public object GetEditor(Type t_type)
{
return TypeDescriptor.GetEditor(this, t_type, true);
}
public EventDescriptorCollection GetEvents()
{
return TypeDescriptor.GetEvents(this,true);
}
public EventDescriptorCollection GetEvents(Attribute[] t_attrs)
{
return TypeDescriptor.GetEvents(this, t_attrs, true);
}
public PropertyDescriptorCollection GetProperties()
{
return TypeDescriptor.GetProperties(this, true);
}
public PropertyDescriptorCollection GetProperties(Attribute[] t_attrs)
{
List<PropertyBase> tmp_props = new List<PropertyBase>();
foreach (PropertyBase tt in m_propertys)
{
if (tt.IsBrowsable)
{
tmp_props.Add(tt);
}
}
PropertyDescriptor[] t_props = new PropertyBaseDescriptor[tmp_props.Count];
int i = -1;
foreach (PropertyBase tt in tmp_props)
{
i++;
t_props[i] = new PropertyBaseDescriptor(tmp_props[i], null);
}
return new PropertyDescriptorCollection(t_props);
}
public object GetPropertyOwner(PropertyDescriptor t_pd)
{
return this;
}
#endregion
}
}
--------------------编程问答-------------------- using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Generator.Design.BLL.Controls;
using System.Drawing.Design;
namespace Generator.Design.BLL
{
public class PropertyChangeBase
{
/// <summary>
/// 此方法是通用的,中间代理类的属性与源对象完全一样
/// </summary>
/// <param name="t_obj"></param>
/// <returns></returns>
public PropertyBaseCollection ObjectToPropertyBase(object t_obj)
{
PropertyDescriptorCollection ts = TypeDescriptor.GetProperties(t_obj);
if (ts.Count <= 0)
{
return null;
}
int iCount = ts.Count;
PropertyBaseCollection pts = new PropertyBaseCollection();
#region 把属性存入中间类中
for (int i = 0; i < iCount; i++)
{
PropertyBase pt = new PropertyBase();
pt.Name = ts[i].Name;
pt.Value = ts[i].GetValue(t_obj);
pt.IsReadOnly = ts[i].IsReadOnly;
pt.IsBrowsable = ts[i].IsBrowsable;
pt.Category = ts[i].Category;
if (!pt.IsReadOnly)
{
if (ts[i].GetEditor(typeof(UITypeEditor)) != null)
{
pt.uiTypeConvertor = (UITypeEditor)ts[i].GetEditor(typeof(UITypeEditor));
}
else
{
pt.uiTypeConvertor = null;
}
}
else
{
pt.uiTypeConvertor = null;
}
pt.Description = ts[i].Description;
try
{
pt.Converter = ts[i].Converter; ;
}
catch
{
pt.Converter = ts[i].Converter;
}
pts.Add(pt);
}
#endregion
return pts;
}
}
}
--------------------编程问答-------------------- 一共有四个类,一个属性基类,一个属性类集合,一个属性描述类,一个中间类(用来动态改变属性的个数,其实是过滤一下而已),因为是继承接口,重写的方法和实现的方法比较多,但思路很简单,你可以参考一下,你的问题应该没这个复杂 --------------------编程问答-------------------- 谢谢 --------------------编程问答-------------------- --------------------编程问答-------------------- 不会,帮顶 --------------------编程问答-------------------- 支持搂主,收藏 --------------------编程问答-------------------- 都是很好的建议! 值得学习
补充:.NET技术 , .NET Framework