表的内容 集合类实现项目类实现方法I 项类型转换器类实现 项目类实现-方法二结论更新 介绍 在本文中,我想演示创建列表框的技术 控件,在每个项目文本的左边绘制一个小图像(见图1)。 此控件公开项集合 属性,其中包含可通过方法编辑的自定义项 Visual Studio的集合编辑器。 图1运行时控件的外观 有几篇文章专门讨论相同的问题 例子列表框的图标由nhgiang。 但这些控件都没有实现具有Items属性的控件 可以通过Visual Studio的Windows窗体设计器进行编辑。 他们使用一些手工创建的代码片段,如: 通过编程方式添加项目——就像在c++中一样,没有Visual c#的优势。
imageListBox.Items.Add(new ImageListBoxItem("Text 1", 0)); imageListBox.Items.Add(new ImageListBoxItem("Text 2", 1)); imageListBox.Items.Add(new ImageListBoxItem("Text 3", 2));
控件的实现在本文中被描述 提供可视化编辑机会,加速开发过程。 但是,当然,它仍然支持以编程的方式管理项。 视觉添加项目-你不需要记住什么索引 与图像列表中的图像关联。所有的编辑都是在 集合编辑器,您不需要触摸代码(见图2)。 图2设计时的采集编辑 在下面的段落中,我将简要地描述我遇到的问题 遇到。为了实现,你最好看看代码——它代表什么 本身。 在项目中使用控件 如果您想先尝试演示项目,请不要 忘记先编译它(至少是ImageListBox控件) ,否则控件将不会在设计时出现在测试表单中 时间。 图3控件的主要属性 如果想在表单上使用ImageListBox, 还请添加ImageList控件到您的表单,填充 然后设置ImageListBox的ImageList属性 然后开始将项目添加到项目属性中(见图3)。 控制类 关于控制类没有太多要说的。的ImageListBox 继承自标准列表框控件。我们应该实现 ImageList属性,该属性允许为 要在列表框中绘制的图像。另一个步骤是覆盖列表框 物品属性。唯一重要的是设置 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)) 属性来通知设计器我们要序列化的内容 集合,而不是设计时的集合本身。的DrawMode 属性设置为OwnerDrawFixed值,然后隐藏 属性[Browsable(false)]。这幅图 是在OnDrawItem保护方法中做的,没有吗 复杂待描述。 集合类实现 有几种实现集合的方法, 作为内部或嵌套类,或以其他方式。在这个 我们将使用基类项集合来存储 集合的对象,因此最好实现该集合 作为嵌套类,以允许访问控件的私有成员。集合 类应该实现IList、ICollection和IEnumerable 接口。在这种情况下,我们不能使用CollectionBase继承 因为有比简单的项存储更复杂的行为。我建议 您需要查看代码以了解实现的细节。另一个重要问题 是为集合类实现这个[int index]属性吗 这将允许访问集合成员。 项目类的实现。方法我 从头实现item类(没有基类) 首先,我们需要为item类实现至少两个构造函数。的 第一个是无参数的,它允许集合编辑器创建一个“空” 将所有属性设置为默认值的项。另一个构造函数是 最大数量的参数需要完全重建所有可编辑 项对象的属性。在我们的例子中,这个是
ImageListBoxItem(string Text, int ImageIndex)
。 item类实现了ISerializable和ICloneable 接口(我不确定是否需要ICloneable,但是 这只是复制ListViewItem实现的一组接口)。 集合编辑器使用ISerializable接口来 允许在编辑器中设置项属性。每个条目序列化两个 属性:文本(字符串)和图像索引(整数)。 的右侧的属性网格中显示这些属性 集合编辑器(见图4) 视图ImageListBoxItem属性。我的方法。 另一个值得注意的问题是让集合编辑器显示正确的值 (以及缩略图)的ImageIndex 财产。我们将通过三个步骤来完成: 将ImageList只读属性添加到项目类中。 把它藏在属性浏览器[Browsable(false)]。 这个属性由分配给ImageIndex的UITypeEditor使用 属性,该值编辑器从该图像列表获取图像 将显示在组合框中。 添加[TypeConverter (typeof (ImageIndexConverter))]属性 在实现ImageIndex属性之前。这 告诉编辑器需要从ImageList获取索引 与项相关联的。 添加(编辑器(“System.Windows.Forms.Design.ImageIndexEditor”, typeof(UITypeEditor))]属性在实现ImageIndex之前 财产。这告诉集合编辑器对属性使用标准UI编辑器 即图像索引。 图5组合框中的图像来自控件的图像列表 你瞧а!下面是填充了所需图片的组合框(见图5)。 项类型转换器类实现 作为最后一笔,我们需要Windows窗体设计器自动添加 为表单的InitializeComponent()函数编写类似的代码 遵循:
this.listBox1.Items.AddRange( new Controls.Development.ImageListBoxItem[] { new Controls.Development.ImageListBoxItem("Granite", 0), new Controls.Development.ImageListBoxItem("Marble", 1), new Controls.Development.ImageListBoxItem("Stone", 2), new Controls.Development.ImageListBoxItem("Stucco", 3) } );
这是通过实现继承的类型转换器类来执行的 从TypeConverter。我们将使用可扩展的模式 (就像微软为ListViewItem所做的那样)来减少 功能覆盖。我们应该重写的唯一函数是CanConvertTo 和ConvertTo。我们应该只转换为InstanceDescriptor Windows窗体设计器使用的类型。ConvertTo函数 通过提供ConstructorInfo填充InstanceDescriptor对象 对于将出现在由设计器添加的代码中的构造函数(在本例中为
ImageListBoxItem(string Text, int ImageIndex)
)。然后,将这个转换器类与 ImageListBoxItem通过[TypeConverter(typeof(ImageListBoxItemConverter))] 属性。现在控件已经准备好由设计器编辑了。 第一种方法的优缺点 优点: 这个类没有任何基类(System.Object除外)。 您可以完全控制已创建的类。 缺点: 本地化并不简单,而且还没有实现,您需要实现类型转换器类 项目类的实现。方法二(可以定位的!) 另一种解决方案是从System.ComponentModel.Component派生集合项类。 在这种情况下,您不需要实现类型转换器类 可串行性。所有其他方法和属性都是相同的。的 在这种情况下,集合编辑器的外观也会有所不同(参见图6) 当代码生成时。 图7 ImageListBoxItem属性。方法二。 自动添加的代码将被分成两部分。首先, 将所有项的成员变量添加到窗体类中。然后在形式的 类InitializeComponent方法调用构造函数 项目,项目被添加到列表框,然后它们的属性被设置。
// Members added to form class automatically private Controls.Development.ImageListBoxItem graniteItem; private Controls.Development.ImageListBoxItem marbleItem; private Controls.Development.ImageListBoxItem stoneItem; private Controls.Development.ImageListBoxItem stuccoItem; ... private void InitializeComponent() { ... // Constructors first called for the class members this.graniteItem = new Controls.Development.ImageListBoxItem(); this.marbleItem = new Controls.Development.ImageListBoxItem(); this.stoneItem = new Controls.Development.ImageListBoxItem(); this.stuccoItem = new Controls.Development.ImageListBoxItem(); ... // Items added to the ImageListBox this.listBox1.Items.AddRange( new Controls.Development.ImageListBoxItem[] { this.graniteItem, this.marbleItem, this.stoneItem, this.stuccoItem}); ... // Member properties set ... // // graniteItem // this.graniteItem.ImageIndex = 0; this.graniteItem.Text = "Granite"; ... }
第二种方法的优缺点 优点: 这种方法最显著的优点是实现简单 现在控件可以通过Windows窗体进行本地化了吗 设计师 不需要类型转换器类 这个类的实现比方法I中的要简单 缺点: 唯一的缺点是项目变得有点重,因为他们 是从组件类派生的 结论 本文演示了将集合公开为属性的方法。 这项技术可能对一组其他控件有用 自定义网格控件的展望栏、列和行标题等)。如果你 花几天时间实现本文中描述的一组类 技术,这将为你在你将要使用的项目中赢得时间 设计控制。无需添加代码行,只需单击、键入和 享受。我已经做到了。 问题 尚未解决的主要问题是方法I的本地化。 我对所有成员I使用[Localizable(true)]属性 希望是可本地化的,但这似乎不能以适当的方式工作。当 我将表单的可本地化属性设为true和 然后尝试在两种语言之间切换ImageListBox的内容 保持不变。如果有人已经解决了这个问题,请与我联系 如果可能的话。我注意到几乎遇到了同样的问题 列表视图控件。 更新 感谢James T. Johnson,现在工具箱位图正确显示了。我 添加了一个嵌入的位图资源(ImageListbox.bmp) 显示在Visual Studio的工具箱中。资源的名称必须匹配 控件的名称(减去项目默认名称空间的名称)。添加了另一种实现支持本地化的item类的方法。 本文转载于:http://www.diyabc.com/frontweb/news279.html