【发布时间】:2017-03-28 11:46:36
【问题描述】:
场景
我继承了ComboBox 类来设计一种 ComboBox 控件,我可以在该控件上为其 ComboBox.Items 集合提供自定义类型 (MyItem)...
这是 ComboBox 的子类:
<DesignerCategory("UserControl")>
Public Class MyComboBox : Inherits ComboBox
<Editor(GetType(CollectionEditor), GetType(UITypeEditor))>
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public Shadows ReadOnly Property Items As MyItemCollection
<DebuggerStepThrough>
Public Sub New()
MyBase.DrawMode = DrawMode.OwnerDrawFixed
Me.Items = New MyItemCollection(owner:=Me)
End Sub
Protected Overrides Sub OnDrawItem(ByVal e As DrawItemEventArgs)
e.DrawBackground()
e.DrawFocusRectangle()
' Check if it is an item from the Items collection.
If (e.Index < 0) Then
' not an item, draw the text.
Using brush As New SolidBrush(e.ForeColor)
e.Graphics.DrawString(Me.Text, e.Font, brush, e.Bounds.Left, e.Bounds.Top)
End Using
Else
' Get the item to draw.
Dim item As MyItem = Me.Items(e.Index)
Using brush As New SolidBrush(e.ForeColor)
e.Graphics.DrawString(item.Text, e.Font, brush, e.Bounds.Left, e.Bounds.Top)
End Using
End If
MyBase.OnDrawItem(e)
End Sub
End Class
这是ComboBox.ObjectCollection 的子类:
<ListBindable(False)>
<DefaultMember("Item")>
Public Class MyItemCollection : Inherits ObjectCollection
Sub New(ByVal owner As MyComboBox)
MyBase.New(owner)
End Sub
<Browsable(False)>
<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
Default Public Overloads Property Item(ByVal index As Integer) As MyItem
Get
Return DirectCast(MyBase.Item(index), MyItem)
End Get
Set(ByVal value As MyItem)
MyBase.Item(index) = value
End Set
End Property
' Original property:
'
'<Browsable(False)>
'<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
'Default Public Overrides Property Item(ByVal index As Integer) As Object
' Get
' Return MyBase.Item(index)
' End Get
' Set(value As Object)
' MyBase.Item(index) = value
' End Set
'End Property
End Class
最后,这是我将用于我的控件的 Items 集合的自定义类型 MyItem:
Public NotInheritable Class MyItem
Public Property Text As String
Public Sub New()
Me.New(String.Empty)
End Sub
Public Sub New(ByVal text As String)
Me.Text = text
End Sub
End Class
所有这些在执行时都可以正常工作,我可以添加项目并且按预期工作,问题是它在设计时无法正常工作......
问题
当我尝试像这样在设计时添加项目时:
...乍一看似乎可行,因为我可以添加项目。
并且该记录似乎由 Visual Studio 在 Form 的 dsigner 类 (Form1.Designer.vb) 中正确自动生成:
Private Sub InitializeComponent()
Me.MyComboBox1 = New MyComboBox()
Dim MyItem1 As MyItem = New MyItem()
MyItem1.Text = "Test"
Me.MyComboBox1.Items.AddRange(New Object() {MyItem1})
' ...
End Sub
更重要的是,如果我尝试在执行时通过调用 Items.Count 属性来确定集合中当前项目的数量,它会给我预期值:
Public Class Form1 : Inherits Form
Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
MessageBox.Show(String.Format("There are '{0}' items in the collection.",
MyComboBox1.Items.Count))
End Sub
End Class
...但是,这些都很重要,因为当我启动应用程序时,我没有看到在设计时添加的项目,我的意思是在设计时添加的项目在执行时没有绘制在控件中时间。
问题
我想做什么?我该如何解决这个问题?。
请注意,这可能不是绘图问题,因为我在执行时通过Items.Add() 和Items.AddRange() 方法添加的项目已正确添加和绘制。
我认为这可能是关于内容同步的某种问题......
我真的不知道发生了什么,因为通过 Visual Studio 的对象检查器,我确保为我的类、方法和属性指定所有属性类,与默认情况下为 ComboBox.Items 属性分配的相同还有ComboBox.ObjectCollection 类和ComboBox.ObjectCollection.Item 成员。
【问题讨论】:
-
您知道您可以(几乎)将任何您想要的类型添加到标准 ListControls(CBO、ListBox)中,对吧?如果您在
MyItem上覆盖ToString(),则文本将显示在集合编辑器中。这些项目的问题是(可能)基础ObjectCollection类不是强类型的。集合编辑器不会知道它确实需要创建一个 MyItem 类型而不是Object -
@Plutonix 感谢您的评论。是的,我知道您可以将任何类型添加到默认对象集合中,但是这样做,VS 设计器将向您显示对象集合 (
<Editor(GetType(ObjectSelectorEditor), GetType(UITypeEditor))>) 的默认编辑器,您只能在该编辑器上添加“原始”对象,没有属性可以设置对象,而不是像我正在使用的特定编辑器 (<Editor(GetType(CollectionEditor), GetType(UITypeEditor))>),您可以在设计时设置对象的属性。 -
集合编辑器已经创建了一个
MyItem对象,上面我展示了在通过集合编辑器添加项目后添加 VS 的自动生成代码。我不明白你的意思是什么区别应该覆盖 ToString 函数以将MyItem对象表示为文本,无论如何我做到了,但它并没有像预期的那样解决问题。 -
遮蔽
Items属性不等同于覆盖虚拟属性。所有使用Items属性的基本ComboBox方法都将使用ComboBox类中定义的方法。您可以使用反射设置基类支持字段,但您还需要考虑任何使支持字段为空的方法,因为Items Property 将重新创建支持字段,如果它是 Nothing。 RefreshItems 方法使支持字段为空, -
很抱歉没有尽快回复您。你误解了我的提议。您可以隐藏
Items属性,但您需要重新实现RefreshItems方法的功能;它是可覆盖的。您将使用反射将 Combox 的itemsCollection字段设置为MyItemCollection的一个实例。您可以在构造函数和重新实现的RefreshItems方法中执行此操作。如果您需要这方面的帮助,我可以发布一份我认为应该可行的 hack 工作。
标签: .net vb.net winforms visual-studio windows-forms-designer