[WinF]Propertygrid 如何实现更改对象的名称"(Name)"属性

assky124 2008-12-02 10:52:27
一般的控件Control类都有个“(Name)”属性,通过修改该属性可以改变Control对象的名字。

请问我如何写我的类MyClass,可以像.net属性编辑器一样 修改创建的MyClass对象的名字?

//例如,我创建了一个对象
MyClass myc1;

我想通过PropertyGrid 把myc1变成 myc2
...全文
599 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
assky124 2008-12-04
  • 打赏
  • 举报
回复

//定义一个控件,用来测试


/// <summary>
/// ItemCollection 的摘要说明。
/// </summary>
public class UCItemCollection : System.Windows.Forms.UserControl
{
private ItemCollections m_items;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;

public UCItemCollection()
{
// 该调用是 Windows.Forms 窗体设计器所必需的。
InitializeComponent();

// TODO: 在 InitializeComponent 调用后添加任何初始化
this.m_items = new ItemCollections();
}

/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器
/// 修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion

[Editor(typeof(System.ComponentModel.Design.CollectionEditor),
typeof(System.Drawing.Design.UITypeEditor))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]//设置设计器是序列化它的内容。
public ItemCollections Items
{
get
{
return this.m_items;
}
}
}


虽然这个方法并不是很好,直接继承类,而不是接口。算是这个方法的美中不足之处吧。
而c#类的继承是只能有一个父类的,不能像C++ 那样多个继承。
要是有个能有接口实现的例子就好了。
assky124 2008-12-04
  • 打赏
  • 举报
回复
多谢 gomoku

问题基本解决
贴上实例代码

//Item和Item的集合类
/// <summary>
/// Item
/// </summary>
public class MyItem:System.ComponentModel.Component
{
private string s_name;
private string s_value;
public MyItem()
{
//
// TODO: 在此处添加构造函数逻辑
//
this.s_name = string.Empty;
this.s_value = string.Empty;
}

/// <summary>
/// 名字
/// </summary>
public string Name
{
get
{
return this.s_name;
}
set
{
this.s_name = value;
}
}

/// <summary>
/// 数值
/// </summary>
public string Value
{
get
{
return this.s_value;
}
set
{
this.s_name = value;
}
}
}

/// <summary>
/// ItemCollection
/// </summary>
public class ItemCollections:System.Collections.CollectionBase
{
public ItemCollections()
{
}

//这个方法必须有
public MyItem this [int index]
{
get
{
return (MyItem)List[index];
}
set
{
List[index] = value;
}

}
public void Add(MyItem item)
{
this.List.Add(item);
}

public void Remove(MyItem item)
{
this.List.Remove(item);
}

public int IndexOf(MyItem item)
{
return this.List.IndexOf(item);
}

protected override void OnInsert(int index, object value)
{
if(!(value is MyItem))
{
throw new ArgumentException("插入Item不正确","未执行");
}
}

protected override void OnSet(int index, object oldValue, object newValue)
{
if(!(newValue is MyItem))
{
throw new ArgumentException("插入Item不正确","未执行");
}
}

}

gomoku 2008-12-03
  • 打赏
  • 举报
回复
本来Array或Collection类型就有UITypeEditor -(System.ComponentModel.Design.ArrayEditor,System.ComponentModel.Design.CollectionEditor)。
你完全可以不用自己写。

如果你要自己写,要理解Visual Studio IDE作为一个设计器所提供的服务。
当你的Component放到设计器上的时候也叫(Sited,中文或许叫进场吧,而恰恰就是IComponent提供了Site这个接口),
通过ISite,你的Component或它所关联的IDesigner,就可以通过GetService来获得设计器所提供的各种服务。

这些服务包括像INameCreationtService(为新建控件取名字的服务),
ITypeDescriptorFilterService(通过该服务为Component加上一些额外的属性,如(name),Locked等等Component运行时没有的属性),
IToolboxService(通过该服务和工具栏交互)
IComponentChangeService(通过服务知道哪些控件被创建了,被删除,被改名了,或被修改了)
等等等等

通过服务不仅可以获得Design View方面的服务,还可以获得Code View方面的服务(可以用来生成和管理代码,Code Serialization),甚至可以获得项目方面的服务。不过,相关的文档并不多见,我建议你先用我在21楼提供的简单写法。

多了这些解释,希望能更好的理解我在10楼提的,只有实现了IComponent,才能放到设计器中的说法。
assky124 2008-12-03
  • 打赏
  • 举报
回复


我添加的UITypeEditor,现在的效果是点击属性窗口的Item属性就会弹出我自己写的一个窗体,我就是想在这个弹出窗体内修改属性,让我的Items的列表做代码响应改变(永久的;似乎是加这个[TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))])。

水平有限现在只能显示一下,还改不了,而且很容易把VS整出错误,基本是堆栈出错。错误原因还没找到。
gomoku 2008-12-03
  • 打赏
  • 举报
回复
还有疑问吗?如果一开始能把问题表达清楚,可以理清你的思维,也可以更快的得到有效的回应。
以下是我描述的全部的代码(新增了两个属性,以避免MyItem出现在工具栏中):


class My : Component
{
private MyItem[] items;
public MyItem[] Items { get { return items; } set { items = value; } }
}

[ToolboxItem(false)]
[DesignTimeVisible(false)]
class MyItem : Component
{
//public int Value { get; set; }
}
Tiger_ldy 2008-12-03
  • 打赏
  • 举报
回复
这样的想法只能想想啊 不好实现吧
gomoku 2008-12-03
  • 打赏
  • 举报
回复
要实现Collection属性,那你添加一个就可以了:


class My : Component
{
private string[] items;
public string[] Items
{
get { return items; }
set { items = value; }
}
}
gomoku 2008-12-03
  • 打赏
  • 举报
回复
没有界面,也可以拖拽。比如Timer,BackGroundWorker这些都是没有界面的组件。
assky124 2008-12-03
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 gomoku 的回复:]
一个类如果是IComponent,那么它就可以放入设计窗口中。(name)并不是真正类的属性,而是设计器通过IExtenderProviderService服务提供的扩展属性。
由于Component实现了IComponent接口,你所要做的就是让你的类继承Component:


C# code
public class My : Component
{
...
[/Quote]

如果只继承Component类的话,没有界面,拖拽是根本不可能的了。
继承Control! Conrol类本身就有Component,也就不存在我的问题了。

我要实现的功能和ListView添加Items属性相类似。点击添加之后会自动添加一个Item并自动起一个名字,比如items1,当然我需要改这个名字。
birdlonger 2008-12-03
  • 打赏
  • 举报
回复
mark xian !you shijian ye haohao xiang xiang !
assky124 2008-12-02
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 flyjimi 的回复:]
即使Control对象的Name也只是在设计时可以修改。
你可以尝试在PropertyGrid中编辑一个自带的Control,比如TextBox。但是控件的Name属性并不会显示在PropertyGrid中。
[/Quote]

当然是在设计时修改,
我就是自定义了一个控件有个Items属性,在设计时点击Items属性时弹出一个窗体,然后可以编辑这个Items列表,就像ListView控件的Items属性一样
flyjimi 2008-12-02
  • 打赏
  • 举报
回复
即使Control对象的Name也只是在设计时可以修改。
你可以尝试在PropertyGrid中编辑一个自带的Control,比如TextBox。但是控件的Name属性并不会显示在PropertyGrid中。
Zeilone 2008-12-02
  • 打赏
  • 举报
回复
这个名字是对象的名称,就跟变量一样,是编译时使用的,不可以动态更改!~~
2#的name是类的成员,就可以跟其它成员一样赋值了
gomoku 2008-12-02
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 assky124 的回复:]
.net 的SDK上说要继承ISite接口,还要设置关联的 IContainer,比较生涩难懂。
谁有例子啊?
[/Quote]

I would suggest you don't do it.

Your PropertyGrid works in the runtime but the code serialization (generating code in the Form1.Designer.cs) happens in the design time.
assky124 2008-12-02
  • 打赏
  • 举报
回复
.net 的SDK上说要继承ISite接口,还要设置关联的 IContainer,比较生涩难懂。

谁有例子啊?
devilli 2008-12-02
  • 打赏
  • 举报
回复
把myc1变成 myc2 是修改对象的名字
而Name属性,是对象属性的修改,不一样吧
快乐乔巴 2008-12-02
  • 打赏
  • 举报
回复
一般的控件Control类都有个“(Name)”属性
你的MyClass类里自己添加一个Name属性就可以了,Control类里的Name属性已经封装好了 所以看不到
cpio 2008-12-02
  • 打赏
  • 举报
回复

控件的Name是用于生成代码时命名的

而你这个是名称已经确定,要进行修改,不一样
bloodish 2008-12-02
  • 打赏
  • 举报
回复
class MyClass
{
string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}

新增一个public的可读写Name属性即可
assky124 2008-12-02
  • 打赏
  • 举报
回复
我把VS 搞死了。。

异常“System.StackOverflowException”在DefaultDomain中发生
加载更多回复(4)

110,578

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧