.net - How to properly implement/inherit a ComboBox.ObjectCollection class for design-time usage? -


scenario


i subclassed combobox class design kind of combobox control on can supply custom type (myitem) combobox.items collection...

this subclassed combobox class:

<designercategory("usercontrol")> public class mycombobox : inherits combobox      <editor(gettype(collectioneditor), gettype(uitypeeditor))>     <designerserializationvisibility(designerserializationvisibility.content)>     public shadows readonly property items myitemcollection      <debuggerstepthrough>     public sub new()         mybase.drawmode = drawmode.ownerdrawfixed         me.items = new myitemcollection(owner:=me)     end sub      protected overrides sub ondrawitem(byval e drawitemeventargs)          e.drawbackground()         e.drawfocusrectangle()          ' check if item items collection.         if (e.index < 0)             ' not item, draw text.             using brush new solidbrush(e.forecolor)                 e.graphics.drawstring(me.text, e.font, brush, e.bounds.left, e.bounds.top)             end using          else             ' item draw.             dim item myitem = me.items(e.index)             using brush 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 

this subclassed combobox.objectcollection class:

<listbindable(false)> <defaultmember("item")> public class myitemcollection : inherits objectcollection      sub new(byval owner mycombobox)         mybase.new(owner)     end sub      <browsable(false)>     <designerserializationvisibility(designerserializationvisibility.hidden)>     default public overloads property item(byval index integer) myitem                     return directcast(mybase.item(index), myitem)         end         set(byval value myitem)             mybase.item(index) = value         end set     end property      ' original property:     '     '<browsable(false)>      '<designerserializationvisibility(designerserializationvisibility.hidden)>     'default public overrides property item(byval index integer) object     '        '        return mybase.item(index)     '    end     '    set(value object)     '        mybase.item(index) = value     '    end set     'end property  end class 

and custom type myitem use items collection of control:

public notinheritable class myitem      public property text string      public sub new()         me.new(string.empty)     end sub      public sub new(byval text string)         me.text = text     end sub  end class 

all works fine @ execution time, can add items , works expected, problem won't work @ design time...

problem


when try add item @ design time this:

enter image description here

...at first sight seems works, because can add item.

and record seems auto-generated visual studio in form's dsigner class (form1.designer.vb):

private sub initializecomponent()     me.mycombobox1 = new mycombobox()     dim myitem1 myitem = new myitem()     myitem1.text = "test"     me.mycombobox1.items.addrange(new object() {myitem1})      ' ... end sub 

even more, if try determine @ execution time current amount of items inside collection calling items.count property, gives me expected value:

public class form1 : inherits form      sub form1_shown(sender object, e eventargs) handles mybase.shown          messagebox.show(string.format("there '{0}' items in collection.",                                        mycombobox1.items.count))      end sub  end class 

...however, of matters, because when launch application don't see item(s) added @ design time, mean items added @ design time not drawn in control @ execution time.

question


what i'm missing do?. how can fix that?.

please note not drawing problem, because items add through items.add() , items.addrange() method @ execution time added , drawn.

i think maybe sort of issue content synchronization...

i don't know happening, because through object inspector of visual studio ensured specify attribute classes classes, methods , properties, same assigned default combobox.items property , combobox.objectcollection class , combobox.objectcollection.item member.

here example of technique mentioned in comments. highly reliant of using reflection set field in combobox class executing methods in class. such, subject breaking if ms ever modifies these items.

edit 2: corrected code

imports system.componentmodel imports system.componentmodel.design imports system.drawing.design imports system.reflection  <designercategory("usercontrol")> public class mycombobox : inherits combobox     private fiitemscollection fieldinfo     private picmitem propertyinfo     private minativeclear methodinfo     private miobjectcollectionaddrangeinternal methodinfo      private _items myitemcollection      <editor(gettype(collectioneditor), gettype(uitypeeditor))>     <designerserializationvisibility(designerserializationvisibility.content)>     public shadows readonly property items myitemcollection                 return me._items         end     end property      <debuggerstepthrough>     public sub new()         mybase.new()         mybase.drawmode = drawmode.ownerdrawfixed         me.fiitemscollection = gettype(combobox).getfield("itemscollection", bindingflags.instance or bindingflags.nonpublic)         me._items = new myitemcollection(me)         fiitemscollection.setvalue(me, me._items)         me.picmitem = gettype(currencymanager).getproperty("item", bindingflags.instance or bindingflags.nonpublic)         me.minativeclear = gettype(combobox).getmethod("nativeclear", bindingflags.instance or bindingflags.nonpublic)         me.miobjectcollectionaddrangeinternal = gettype(objectcollection).getmethod("addrangeinternal", bindingflags.instance or bindingflags.nonpublic)     end sub      protected overrides sub refreshitems()         dim selectedindex integer = me.selectedindex         dim itemscollection myitemcollection = me._items         me._items = nothing          dim destination object() = nothing         if ((not mybase.datamanager nothing) andalso (mybase.datamanager.count <> -1))             destination = new object(mybase.datamanager.count - 1) {}             dim args(0 0) object             int32 = 0 destination.length - 1                 args(0) =                 destination(i) = picmitem.getvalue(mybase.datamanager, args)             next         elseif (not itemscollection nothing)             destination = new object(itemscollection.count - 1) {}             itemscollection.copyto(destination, 0)         end if          me.beginupdate()          try             if mybase.ishandlecreated                 me.minativeclear.invoke(me, nothing)             end if             if (not destination nothing)                 me._items = new myitemcollection(me)                 me.miobjectcollectionaddrangeinternal.invoke(me._items, new object() {destination})                 me.fiitemscollection.setvalue(me, me._items)             end if             if (not mybase.datamanager nothing)                 me.selectedindex = mybase.datamanager.position             else                 me.selectedindex = selectedindex             end if                     me.endupdate()         end try     end sub      protected overrides sub ondrawitem(byval e drawitemeventargs)         e.drawbackground()         e.drawfocusrectangle()         ' check if item items collection.         if (e.index < 0)             ' not item, draw text.             using brush new solidbrush(e.forecolor)                     e.graphics.drawstring(me.text, e.font, brush, e.bounds.left, e.bounds.top)             end using         else             ' item draw.             dim item myitem = me.items(e.index)             using brush 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 

Comments

Popular posts from this blog

javascript - Clear button on addentry page doesn't work -

c# - Selenium Authentication Popup preventing driver close or quit -

tensorflow when input_data MNIST_data , zlib.error: Error -3 while decompressing: invalid block type -