สำนักวิทยบริการและเทคโนโลยีสารสนเทศ (สวส.)

Office of Academic Resources and Information Technology

ตัวควบคุมกล่องรายการหรือ ComboBox ตัวควบคุมคัดเลือกรายการหลายครั้ง ใน Visual Basic .NET

อาการ    คุณมีฟอร์ม Microsoft Windows ที่ มีตัวควบคุมกล่องรายการหรือComboBoxตัวควบคุม เมื่อคุณผูกListBoxหรือComboBoxกับแหล่งข้อมูล ตัวควบคุมคัดสินค้าในรายการหลายครั้ง
สาเหตุ   เมื่อคุณสร้างกล่องรายการหรือเมื่อคุณสร้างComboBoxแบบฟอร์มที่ไม่มีคุณสมบัติBindingContext กล่องรายการหรือComboBoxต้องมีBindingContextเมื่อต้องการคัดลอกข้อมูล ดังนั้น ตัวควบคุมขอให้ ฟอร์มส่งBindingContext แบบฟอร์มสร้างBindingContextและแบบฟอร์มการแจ้งเตือนไปยังตัวควบคุมแรกทำแล้ว กล่องรายการหรือComboBoxได้รับการแจ้งเตือน และตัวควบคุมพยายามปรับปรุงคุณสมบัติDataManager ดังนั้นListBoxหรือComboBoxสร้างสำเนาของรายการแรก เมื่อแบบฟอร์มสร้างBindingContext, ListBoxหรือComboBoxสร้างสำเนาชุดที่สองของรายการ
 เมื่อต้องแก้ไขปัญหานี้ ใช้ขั้นตอนต่อไปนี้:
  • การตั้งค่าคุณสมบัติBindingContextของตัวควบคุมก่อนที่คุณตั้งค่าการผูกข้อมูลใด ๆ
  • การตั้งค่าคุณสมบัติDisplayMemberของตัวควบคุมก่อนที่คุณตั้งค่าคุณสมบัติแหล่งข้อมูล
เมื่อต้องใช้กระบวนงานเหล่านี้ ให้ทำตามขั้นตอนเหล่านี้:
  1. รหัสที่มีอยู่ในตัวสร้างแบบฟอร์ม fแทนที่ ด้วยรหัสต่อไปนี้
    Dim pt As ProductTypes = New ProductTypes
'Add a ComboBox control to the form.
Dim cb As ComboBox = New ComboBox
Controls.Add(cb)
'Invoke the binding context for the ComboBox.
Dim bc As New BindingContext
cb.BindingContext = bc
'Set the DataSource property and set the DisplayMember property of the ComboBox.
cb.DisplayMember = "Description"
cb.DataSource = pt
หมายเหตุ คุณยังสามารถใช้รหัสนี้สำหรับตัวควบคุมกล่องรายการด้วยการแทนComboBoxด้วยกล่องรายการ.
2.ตรวจแก้จุดบกพร่องเมนู คลิกเริ่มการทำงาน.
                วิธีการCopyToนั้นเพียงครั้งเดียว
สถานะ   Microsoft ยืนยันว่า ปัญหานี้เป็นปัญหาที่เกิดขึ้นกับผลิตภัณฑ์ของ Microsoft ซึ่งมีการระบุไว้ในส่วน"ใช้งาน"
ข้อมูลเพิ่มเติม  ขั้นตอนในการทบทวนเกิดลักษณะการทำงาน
1.  ใน Microsoft Visual Studio .NET เริ่มต้นโปรแกรมประยุกต์ Windows ใหม่ โดยใช้ Visual Basic .NET หรือ Visual C# .NET
       โดยค่าเริ่มต้น Form1 ถูกสร้างขึ้น
2.  รหัสที่มีอยู่ใน Form1 แทนที่ ด้วยรหัสต่อไปนี้
             รหัส.NET Visual Basic
Imports System.Windows.Forms
Class f
    Inherits Form
    Shared Sub Main()
        Application.Run(New f)
    End Sub
    Private Sub New()
        Dim pt As ProductTypes = New ProductTypes
        'Add a ComboBox control to the form.
        Dim cb As ComboBox = New ComboBox
        Controls.Add(cb)
        'Set the DataSource property and set the DisplayMember property of the ComboBox.
        cb.DataSource = pt
        cb.DisplayMember = "Description"
    End Sub
End Class
  หมายเหตุ  คุณยังสามารถใช้รหัสนี้สำหรับตัวควบคุมกล่องรายการด้วยการแทนComboBoxด้วยกล่องรายการ.
3. บนเมนูโครงการคลิกเพิ่มคลาสและจากนั้น คลิกเปิด.
4. แทนรหัสที่มีอยู่ในClass1กับรหัสต่อไปนี้
            รหัส.NET Visual Basic
Imports System
Imports System.ComponentModel
Imports System.Collections
Imports System.Data
Imports System.Data.SqlClient
Public Class ProductTypes
    Implements IList
    Implements IEnumerator
    Private position As Integer = -1
    'List of items
    Private _Cache As Hashtable
    'List of ordinal pointers to the items
    Private _CacheOrdinal As Hashtable
    Public Sub New()
        _Cache = New Hashtable
        _CacheOrdinal = New Hashtable
        FillCache()
    End Sub
    Public Function GetEnumerator() As ProductTypes
        position = -1
        Console.WriteLine("In type GetEnum..." + Environment.StackTrace)
        Return (Me)
    End Function
    Private Function IGetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
        position = -1
        Console.WriteLine("In IEnum GetEnum..." + Environment.StackTrace)
        Return CType((Me), IEnumerator)
    End Function
    ' IList
    Public ReadOnly Property IsFixedSize() As Boolean Implements IList.IsFixedSize
        Get
            Return (False)
        End Get
    End Property
    ' IList
    Public ReadOnly Property IsReadOnly() As Boolean Implements IList.IsReadOnly
        Get
            Return (False)
        End Get
    End Property
    Public Property IItem(ByVal index As Integer) As Object Implements IList.Item
        Get
            Console.WriteLine("In IList this...")
            Return (CType(_Cache(_CacheOrdinal(index)), ProductType))
        End Get
        Set(ByVal Value As Object)
        End Set
    End Property
    Default Property Item(ByVal pos As Integer) As ProductType
        Get
            Console.WriteLine("In type this...")
            Return (CType(_Cache(_CacheOrdinal(pos)), ProductType))
        End Get
        Set(ByVal Value As ProductType)
        End Set
    End Property
    ' ICollection
    Public ReadOnly Property Count() As Integer Implements ICollection.Count
        Get
            Console.WriteLine("In Count()")
            Return (_Cache.Count)
        End Get
    End Property
    ' Declare the Reset method that IEnumerator requires:
    Public Sub Reset() Implements IEnumerator.Reset
        Console.WriteLine("Called reset")
        position = -1
    End Sub
    ' Declare the MoveNext method that IEnumerator requires:
    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        If position < _Cache.Count - 1 Then
            position = position + 1
            Return True
        Else
            Return False
        End If
    End Function
    Public Function Add(ByVal o As Object) As Integer Implements IList.Add
        Return 1
    End Function
    Public Sub Clear() Implements IList.Clear
    End Sub
    Public Sub RemoveAt(ByVal i As Integer) Implements IList.RemoveAt
    End Sub
    Public Sub Remove(ByVal o As Object) Implements IList.Remove
    End Sub
    Public Function IndexOf(ByVal o As Object) As Integer Implements IList.IndexOf
        Return 0
    End Function
    Public Function Contains(ByVal o As Object) As Boolean Implements IList.Contains
        Return False
    End Function
    Public ReadOnly Property IsSynchronized() As Boolean Implements ICollection.IsSynchronized
        Get
            Return (False)
        End Get
    End Property
    Public ReadOnly Property SyncRoot() As Object Implements ICollection.SyncRoot
        Get
            Return (Nothing)
        End Get
    End Property
    Public Sub Insert(ByVal i As Integer, ByVal o As Object) Implements IList.Insert
    End Sub
    Public ReadOnly Property Current() As ProductType
        Get
            Return CType(_Cache(_CacheOrdinal(position)), ProductType)
        End Get
    End Property
 
    ' Declare the Current property that IEnumerator requires:
    Public ReadOnly Property ICurrent() As Object Implements IEnumerator.Current
        Get
            Return _Cache(_CacheOrdinal(position))
        End Get
    End Property
    Default Property Item(ByVal productTypeId As String) As ProductType
        Get
            Return CType((_Cache(productTypeId)), ProductType)
        End Get
        Set(ByVal Value As ProductType)
        End Set
    End Property
    Public Sub CopyTo(ByVal arr As System.Array, ByVal i As Integer) Implements ICollection.CopyTo
        _Cache.CopyTo(arr, i)
        Console.WriteLine("Calling copy..." + Environment.StackTrace)
    End Sub
    Private Sub FillCache()
        Dim ordinal As Integer = 0
        Dim pType As ProductType = New ProductType
        pType.Description = "eric"
        pType.ProductTypeId = System.Guid.NewGuid()
        _Cache.Add(pType.ProductTypeId, pType)
        _CacheOrdinal.Add(ordinal, pType.ProductTypeId)
        ordinal = ordinal + 1
        Dim pType1 As ProductType = New ProductType
        pType1.Description = "nancy"
        pType1.ProductTypeId = System.Guid.NewGuid()
        _Cache.Add(pType1.ProductTypeId, pType1)
        _CacheOrdinal.Add(ordinal, pType1.ProductTypeId)
        ordinal = ordinal + 1
    End Sub
End Class
Public Class ProductType
    Private _ProductTypeId As Guid
    Private _Description As String
    Public Sub New()
        _ProductTypeId = System.Guid.NewGuid()
        _Description = Nothing
    End Sub
    Public Property ProductTypeId() As Guid
        Get
            Return (_ProductTypeId)
        End Get
        Set(ByVal Value As Guid)
            _ProductTypeId = Value
        End Set
    End Property
    Public Property Description() As String
        Get
            Return (_Description)
        End Get
        Set(ByVal Value As String)
            _Description = Value
        End Set
    End Property
End Class
5.  คลิกขวาWindowsApplication1และจากนั้น คลิกคุณสมบัติ.
6.  ในรายการชนิดของผลผลิตคลิกแอพลิเคชันของคอนโซล.
7.  ในรายการเริ่มต้นวัตถุคลิกfและจากนั้น คลิกตกลง.
8.  บนเมนูสร้างคลิกสร้างวิธีแก้ไขปัญหา.
9.  ตรวจแก้จุดบกพร่องเมนู คลิกเริ่มการทำงาน.
           สังเกตผลลัพธ์ในคอนโซล วิธีการCopyToและวิธีการGetEnumeratorเรียกว่าหลายครั้ง ถึงแม้ว่าคุณอาจคาดว่าวิธีการGetEnumeratorการเรียกครั้งที่สองและวิธีการCopyToจะเรียกเพียงครั้งเดียว
 
           สำหรับข้อมูลเพิ่มเติม โปรดเยี่ยมชมต่อไปนี้ในการเชื่อมโยงในเว็บไซต์ของ Microsoft สำหรับนักพัฒนาเครือข่าย (MSDN):