2014-07-08 5 views
1

목록에 바인딩 된 목록 상자가 클래스입니다. 새 항목을 목록에 추가 할 때까지 모두 제대로 작동합니다. 이 과정에서 데이터 소스는 목록을 새로 고칠 수 없도록 설정되고 '새로 고침'은 처리하지 않습니다. 목록이 새로 고쳐지고 목록 상자 데이터에 바인딩 된 다른 컨트롤은 목록이 있고 올바르게 표시되지만 목록에 스크롤 막대가 표시 되어도 목록이 비어있는 것으로 표시됩니다. 나는 단지 글꼴 색을 바꾸려고 노력했다. 아무것도 없다!바운드 목록 상자는 데이터 새로 고침시 항목을 보이지 않게합니다. 왜?

누군가 이런 일이 발생하는 이유를 알고 있습니까? 그것을 고치는 방법? 또는 새로 고치는 더 좋은 방법?

코드 :

Private Sub btnNew_Click(sender As Object, e As EventArgs) Handles btnNew.Click 

    'lbNames is the listbox carrying all the data 
    Dim oContacts As List(Of clsContact) = lbNames.DataSource 
    lbNames.DataSource = Nothing 

    'Build the new Item, add it to the collection 
    Dim oNewCont As New clsContact 
    oNewCont.Editable = True 
    oNewCont.IsActive = True 
    oNewCont.Firstname = "Jimmy" 
    oNewCont.Lastname = "Smith" 
    oContacts.Add(oNewCont) 

    lbNames.Refresh() 

    ' Re-Set up Autocomplete text box 
    Dim MySource As New AutoCompleteStringCollection() 
    For Each oc As clsContact In oContacts 
     MySource.Add(oc.FullName) 
    Next 
    txtName.AutoCompleteMode = AutoCompleteMode.Suggest 
    txtName.AutoCompleteCustomSource = MySource 
    txtName.AutoCompleteSource = AutoCompleteSource.CustomSource 

    'Set List Box data back to the collection 
    lbNames.DataSource = oContacts 
    lbNames.DisplayMember = "FullName" 

End Sub 

출발 LOAD : 당신은 잘못된 도구를 사용하고

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

    Dim oCont As List(Of clsContact) 
    lbNames.DrawMode = DrawMode.OwnerDrawVariable 

    Dim oTypes As List(Of clsPhoneType) = loadTypes() 
    cboPhoneType.DataSource = oTypes 
    cboPhoneType.DisplayMember = "Type" 
    cboPhoneType.ValueMember = "ID" 

    oCont = LoadNames() 
    lbNames.DataSource = oCont 
    lbNames.DisplayMember = "FullName" 

    Dim MySource As New AutoCompleteStringCollection() 
    For Each oc As clsContact In oCont 
     MySource.Add(oc.FullName) 
    Next 
    txtName.AutoCompleteMode = AutoCompleteMode.Suggest 
    txtName.AutoCompleteCustomSource = MySource 
    txtName.AutoCompleteSource = AutoCompleteSource.CustomSource 
End Sub 

Private Sub lbNames_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles lbNames.DrawItem 

    e.DrawBackground() 

    Dim textBrush As Brush = Brushes.Black 
    Dim drawFont As System.Drawing.Font = e.Font 

    If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then 
     e.Graphics.FillRectangle(Brushes.WhiteSmoke, e.Bounds) 
    End If 

    Dim oCont As clsContact = DirectCast(sender, System.Windows.Forms.ListBox).Items(e.Index) 
    If oCont.IsActive Then 
     textBrush = Brushes.Black 
     If oCont.IsDirty Then textBrush = Brushes.LightCoral 
    Else 
     textBrush = Brushes.LightGray 
    End If 

    Dim str = oCont.FullName 
    e.Graphics.DrawString(str, e.Font, textBrush, e.Bounds, StringFormat.GenericDefault) 
    e.DrawFocusRectangle() 

End Sub 

enter image description here

+0

당신이() lbNames.Refresh을 제거하기 위해 시도 할 수 있습니다 처리? – DevelopmentIsMyPassion

+0

아무런 차이가 없습니다. – GDutton

+0

'oCont' 만 FormLoad에 존재합니다 - 모듈 수준으로 만드십시오 var – Plutonix

답변

0

. List(Of T)은 어떤 이벤트도 발생시키지 않습니다. 컨트롤에 바인딩되면 컨트롤에서 항목이 추가/제거/이동되었는지 여부를 알 수 없습니다. 다행히도 BindingList(Of T)이 구출됩니다. 목록이 수정 될 때마다 ListChanged 이벤트가 발생합니다. 보너스로 클래스/모델이 INotifyPropertyChanged 인터페이스를 구현하는 경우 컨트롤에 속성 변경 사항도 반영됩니다.

lbNames.DataSource = New BindingList(Of clsContact)(oCont) 

여기 당신에게 기본을 보여주기 위해 샘플 양식입니다 :

Imports System.ComponentModel 

Public Class Form1 

    Public Sub New() 
     Me.InitializeComponent() 
     Me.btnAdd = New Button With {.TabIndex = 0, .Dock = DockStyle.Top, .Height = 30, .Text = "Add new contact"} 
     Me.btnChange = New Button With {.TabIndex = 1, .Dock = DockStyle.Top, .Height = 30, .Text = "Change random contact name"} 
     Me.lbContacts = New ListBox With {.TabIndex = 2, .Dock = DockStyle.Fill} 
     Me.Controls.AddRange({Me.lbContacts, Me.btnChange, Me.btnAdd}) 
    End Sub 

    Private Sub HandleMeLoad(sender As Object, e As EventArgs) Handles Me.Load 
     Dim list As New List(Of Contact) 
     For i As Integer = 1 To 10 
      list.Add(New Contact With {.Name = String.Format("Contact # {0}", i)}) 
     Next 
     Me.lbContacts.DataSource = New BindingList(Of Contact)(list) 
     Me.lbContacts.DisplayMember = "Name" 
    End Sub 

    Private Sub HandleButtonAddClick(sender As Object, e As EventArgs) Handles btnAdd.Click 
     Dim list As BindingList(Of Contact) = DirectCast(Me.lbContacts.DataSource, BindingList(Of Contact)) 
     list.Add(New Contact With {.Name = String.Format("Contact # {0}", (list.Count + 1))}) 
    End Sub 

    Private Sub HandleButtonChangeClick(sender As Object, e As EventArgs) Handles btnChange.Click 
     Static rnd As New Random() 
     Dim list As BindingList(Of Contact) = DirectCast(Me.lbContacts.DataSource, BindingList(Of Contact)) 
     If (list.Count > 0) Then 
      With list.Item(rnd.Next(0, list.Count)) 
       .Name = Guid.NewGuid().ToString() 
      End With 
     End If 
    End Sub 

    Public Class Contact 
     Implements INotifyPropertyChanged 
     Public Event PropertyChanged As PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged 
     Public Property Name As String 
      Get 
       Return Me.m_name 
      End Get 
      Set(value As String) 
       If (value <> Me.m_name) Then 
        Me.m_name = value 
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Name")) 
       End If 
      End Set 
     End Property 
     Private m_name As String 
    End Class 

    Private WithEvents btnAdd As Button 
    Private WithEvents btnChange As Button 
    Private WithEvents lbContacts As ListBox 

End Class 
+0

컨트롤에서 항목을 추가하거나 제거해야한다는 사실을 모르는 사실은 데이터 원본을 제거하고 업데이트 된 컬렉션으로 다시 설정 한 이유입니다.데이터 소스를 설정 한 후에 항목이 목록에서 더 이상 볼 수없는 이유를 실제로 설명하지는 않습니다. 항목을 클릭하면 텍스트 상자 값이 변경됩니다. 나는 단지 그들을 볼 수 없다 ?? !! – GDutton

+0

주어진 코드로 문제를 재현 할 수 없어 * why * 대답 할 수 없습니다. 그러나 'BindingList '또는 'ObservableCollection '을 사용하는 것이 좋습니다. '.Items' 속성에 데이터가 있는지 확인 했습니까? –

+0

새로 추가 된 항목이 그대로 있더라도 모든 데이터가 손상되지 않습니다. 그것의 개최 모든 것이 잘 나에게 그것을 보여주지 않기로 선택! – GDutton

0

이 문제를 해결하는 솔루션이 다시 정상으로 drawmode 플립 것 같다. 추가 : lbNames.DrawMode = DrawMode.Normal lbNames.DrawMode = DrawMode.OwnerDrawVariable 문제를 해결합니다.

데이터 소스가 연결될 때 목록의 컨테스트가 다시 그려지지 않으므로 어떤 이유로 인해 드로잉 핸들러가 연결이 끊어지는 것 같아요.

내 새로운 작업 코드 : 개인 서브 btnNew_Click (개체로 보낸 사람, EventArgs입니다으로 e)는 btnNew.Click

'lbNames is the listbox carrying all the data 
    Dim oContacts As List(Of clsContact) = lbNames.DataSource 
    lbNames.DataSource = Nothing 

    'Build the new Item, add it to the collection 
    Dim oNewCont As New clsContact 
    oNewCont.Editable = True 
    oNewCont.IsActive = True 
    oNewCont.Firstname = "Jimmy" 
    oNewCont.Lastname = "Smith" 
    oContacts.Add(oNewCont) 

    ' Re-Set up Autocomplete text box 
    Dim MySource As New AutoCompleteStringCollection() 
    For Each oc As clsContact In oContacts 
     MySource.Add(oc.FullName) 
    Next 
    txtName.AutoCompleteMode = AutoCompleteMode.Suggest 
    txtName.AutoCompleteCustomSource = MySource 
    txtName.AutoCompleteSource = AutoCompleteSource.CustomSource 

    'Set List Box data back to the collection 
    lbNames.DataSource = oContacts 
    lbNames.DisplayMember = "FullName" 

    lbNames.DrawMode = DrawMode.Normal 
    lbNames.DrawMode = DrawMode.OwnerDrawVariable 

End Sub 
관련 문제