QA@IT

ComboBoxを継承し作成したカスタムコントロールのリストを選択したときに 「System.ArgumentOutOfRangeException 」が発生する

6962 PV

ComboBox.Items.Clearメソッドをオーバーライドし、
Clearメソッド内にて任意の処理(手入力された文字列の削除)を行おうとしているのですが、
掲題のエラーが発生して困っております。

やったこと:
ComboBoxを継承したクラス「ComboBoxEx.vb」を作成
ComboBox.ObjectCollectionを継承したクラス「ObjectCollectionEx.vb」を作成
ComboBoxExクラスに「Public Shadows ReadOnly Property Items As ObjectCollectionEx」を定義
ObjectCollectionExクラスに「Public Shadows Sub Clear()」を定義

Form1のデザイナにコントロールを追加、ItemsにAddし、その項目を選択すると以下の例外が発生する

Googleなどで調べて以下のリンク等を読んだのですが、原因が分かりません。
http://social.msdn.microsoft.com/Forums/ja-JP/b0d5d5b8-5774-40ff-a0ac-bb490224715f/combobox0-invalidargumentvalue-index-
http://hpcgi1.nifty.com/MADIA/VBBBS2/wwwlng.cgi?print+200812/08120002.txt

どなたかご存知の方がいらっしゃいましたらご教授をお願い致します。

よろしくお願い致します。

System.ArgumentOutOfRangeException はハンドルされませんでした。
HResult=-2146233086
Message='4' の InvalidArgument=Value は 'index' に対して有効ではありません。
パラメーター名: index
Source=System.Windows.Forms
ParamName=index
StackTrace:
場所 System.Windows.Forms.ComboBox.ObjectCollection.get_Item(Int32 index)
場所 System.Windows.Forms.ComboBox.get_SelectedItem()
場所 System.Windows.Forms.ComboBox.get_Text()
場所 System.Windows.Forms.ComboBox.WmReflectCommand(Message& m)
場所 System.Windows.Forms.ComboBox.WndProc(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
場所 System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
場所 System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam)
場所 System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m)
場所 System.Windows.Forms.Control.WmCommand(Message& m)
場所 System.Windows.Forms.Control.WndProc(Message& m)
場所 System.Windows.Forms.ScrollableControl.WndProc(Message& m)
場所 System.Windows.Forms.ContainerControl.WndProc(Message& m)
場所 System.Windows.Forms.Form.WndProc(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
場所 System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
場所 System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
場所 System.Windows.Forms.Control.DefWndProc(Message& m)
場所 System.Windows.Forms.Control.WmCommand(Message& m)
場所 System.Windows.Forms.Control.WndProc(Message& m)
場所 System.Windows.Forms.ComboBox.WndProc(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
場所 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
場所 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
場所 System.Windows.Forms.Application.Run(ApplicationContext context)
場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
場所 WindowsApplication1.My.MyApplication.Main(String[] Args) 場所 17d14f5c-a337-4978-8281-53493378c1071.vb:行 81
場所 System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
場所 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
場所 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
場所 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
場所 System.Threading.ThreadHelper.ThreadStart()
InnerException:

ComboBoxEx.vb

Public Class ComboBoxEx
    Inherits System.Windows.Forms.ComboBox


    Private Sub InitializeComponent()
        Me.SuspendLayout()
        '
        'ComboBoxEx
        '
        Me.ResumeLayout(False)

    End Sub

    Private Shared _Items As ObjectCollectionEx

    Public Shadows ReadOnly Property Items As ObjectCollectionEx
        Get
            If (_Items Is Nothing) Then
                _Items = New ObjectCollectionEx(Me)
            End If

            Return _Items
        End Get
    End Property


    Public Shadows Event SelectedIndexChanged(ByVal s As Object, ByVal e As System.EventArgs)

    Protected Overrides Sub OnSelectedIndexChanged(ByVal e As System.EventArgs)
        RaiseEvent SelectedIndexChanged(Me.Parent, e)
    End Sub

End Class

ObjectCollectionEx.vb

Public Class ObjectCollectionEx
    Inherits System.Windows.Forms.ComboBox.ObjectCollection
    Implements IList, ICollection

    Private Property cmb As ComboBoxEx

    Public Sub New(ByVal comboBoxEx As ComboBoxEx)
        MyBase.New(comboBoxEx)

        cmb = comboBoxEx
    End Sub

    Public Shadows Sub Clear()
        MyBase.Clear()
        cmb.Text = ""
    End Sub
End Class

Form1.vb

Public Class Form1
    Public Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。


    End Sub

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        ComboBoxEx1.Items.Add("a")
        ComboBoxEx1.Items.Add("b")
        ComboBoxEx1.Items.Add("c")
        ComboBoxEx1.Items.Add("d")
        ComboBoxEx1.Items.Add("e")


        ComboBox1.Items.Add("a")
        ComboBox1.Items.Add("b")
        ComboBox1.Items.Add("c")
        ComboBox1.Items.Add("d")
        ComboBox1.Items.Add("e")
    End Sub


End Class

Form1.Designer.vb

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'フォームがコンポーネントの一覧をクリーンアップするために dispose をオーバーライドします。
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Windows フォーム デザイナーで必要です。
    Private components As System.ComponentModel.IContainer

    'メモ: 以下のプロシージャは Windows フォーム デザイナーで必要です。
    'Windows フォーム デザイナーを使用して変更できます。  
    'コード エディターを使って変更しないでください。
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.ComboBox1 = New System.Windows.Forms.ComboBox()
        Me.Button1 = New System.Windows.Forms.Button()
        Me.ComboBoxEx1 = New WindowsApplication1.ComboBoxEx()
        Me.SuspendLayout()
        '
        'ComboBox1
        '
        Me.ComboBox1.FormattingEnabled = True
        Me.ComboBox1.Location = New System.Drawing.Point(12, 150)
        Me.ComboBox1.Name = "ComboBox1"
        Me.ComboBox1.Size = New System.Drawing.Size(121, 20)
        Me.ComboBox1.TabIndex = 2
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(164, 76)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(75, 23)
        Me.Button1.TabIndex = 3
        Me.Button1.Text = "Button1"
        Me.Button1.UseVisualStyleBackColor = True
        '
        'ComboBoxEx1
        '
        Me.ComboBoxEx1.FormattingEnabled = True
        Me.ComboBoxEx1.Location = New System.Drawing.Point(12, 12)
        Me.ComboBoxEx1.Name = "ComboBoxEx1"
        Me.ComboBoxEx1.Size = New System.Drawing.Size(121, 20)
        Me.ComboBoxEx1.TabIndex = 1
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(284, 262)
        Me.Controls.Add(Me.Button1)
        Me.Controls.Add(Me.ComboBox1)
        Me.Controls.Add(Me.ComboBoxEx1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)

    End Sub
    Friend WithEvents ComboBoxEx1 As WindowsApplication1.ComboBoxEx
    Friend WithEvents ComboBox1 As System.Windows.Forms.ComboBox
    Friend WithEvents Button1 As System.Windows.Forms.Button

End Class

  • windowsやVisual Studioなどのバージョンなどを教えてください。 -
  • flied_onionさん
    申し訳ございません。基本的なことを書き忘れてました。

    Windows7 Professional SP1
    Visual Studio 2010 Express
    .NET Framework 4

    よろしくお願い致します。
    -
  • ちなみに、Shadowsを使った場合はオーバーライドではありません。「Clear時に手入力された文字列の削除」というのがよくわからないんですが、どういった処理を実現されたいのでしょう? -

回答

ComboBoxEx.Items.Clear

でなくても

ComboBoxEx.Clear

として実装すればよいのでは?

例外になっているのは
ComboBox.Items に対しAddされていないので
ComboBoxEx でSelectされたときItemを取得するのにComboBox.Items
SelectedIndex に該当するItemが無い為エラーとなっていると思われます。

編集 履歴 (0)

あまり深く見れていませんが、ShadowsでItemsプロパティを強制的に上書きしているものの、内部ではプロパティでアクセスしていない(privateメンバに直接アクセスしている)場合や、親クラスにキャストするとShadowsは効かない(っていう言い方は微妙か)といったことが影響してるのかなと思いました。

編集 履歴 (0)

flied_onionさん
申し訳ございません。基本的なことを書き忘れてました。

Windows7 Professional SP1
Visual Studio 2010 Express
.NET Framework 4

よろしくお願い致します。

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。