Steht alles in der MSDN Aber hier ist ein Beispiel, was ich irgendwann eher als Übung geschrieben habe. Zuerst eine generische BindingList-Klasse mit .Sort() (eine Spalte) und .Find() Unterstützung.
Imports System.ComponentModel
Imports System.Collections.ObjectModel
' BindableCollection(Of ) with Find, Sort (1 column)
Public Class BindableCollection(Of T)
Inherits BindingList(Of T)
Private _sorted As Boolean = False
Private _sortDirection As ListSortDirection = ListSortDirection.Ascending
Private _sortProperty As PropertyDescriptor = Nothing
Protected Overrides ReadOnly Property IsSortedCore() As Boolean
Get
Return _sorted
End Get
End Property
Protected Overrides Sub ApplySortCore(ByVal pd As _
System.ComponentModel.PropertyDescriptor, ByVal direction As _
System.ComponentModel.ListSortDirection)
_sortDirection = direction
_sortProperty = pd
Dim list = DirectCast(Me.Items, List(Of T))
If list Is Nothing Then Return
list.Sort(New ItemComparer(Of T)(pd, direction))
_sorted = True
OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
End Sub
Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
Get
Return True
End Get
End Property
Protected Overrides ReadOnly Property SortPropertyCore() As _
System.ComponentModel.PropertyDescriptor
Get
Return _sortProperty
End Get
End Property
Protected Overrides ReadOnly Property SortDirectionCore() As _
System.ComponentModel.ListSortDirection
Get
Return _sortDirection
End Get
End Property
Protected Overrides ReadOnly Property SupportsSearchingCore() As Boolean
Get
Return True
End Get
End Property
Protected Overrides Function FindCore(ByVal prop As _
System.ComponentModel.PropertyDescriptor, ByVal key As Object) As Integer
If key.GetType() Is prop.PropertyType Then
For i As Integer = 0 To Items.Count - 1
'If DirectCast(prop.GetValue(Items(i)), IComparable).CompareTo(
' key) = 0 Then
If prop.GetValue(Items(i)).Equals(key) Then
Return i
End If
Next
Return -1
End If
Throw New ArgumentException("Incorrect key type")
End Function
Public ReadOnly Property SortProperty() As PropertyDescriptor
Get
Return _sortProperty
End Get
End Property
Private Class ItemComparer(Of C)
Implements IComparer(Of C)
Private _pd As System.ComponentModel.PropertyDescriptor
Private _direction As Integer
Public Sub New(ByVal pd As PropertyDescriptor, ByVal direction As _
ListSortDirection)
_pd = pd
_direction = If(direction = ListSortDirection.Ascending, 1, -1)
End Sub
Public Function Compare(ByVal x As C, ByVal y As C) As Integer _
Implements System.Collections.Generic.IComparer(Of C).Compare
Return _direction * DirectCast(_pd.GetValue(x), _
IComparable).CompareTo(_pd.GetValue(y))
End Function
End Class
End Class Dann haben wir ein BusinessObject mc, das IEditableObject und INotifyPropertyChanged u.a. unterstützt
Imports System.ComponentModel
Imports System.Collections.ObjectModel
' (Business) Data Object
Public Class mc
Implements INotifyPropertyChanged, IEditableObject, IDataErrorInfo
' Data fields
Private _i As Integer
Private _s As String
'Initial values
Private _ii As Integer
Private _si As String
Private _hasChanges As Boolean
' IEditableObject fields
Private _io As Integer
Private _so As String
Private _editing As Boolean
' IDataErrorInfo fields
Private _itemMessage As String = String.Empty
Private _propertyMessages As New Dictionary(Of String, String)
Private _hasErrors As Boolean
' External Properties
Public Property I() As Integer
Get
Return _i
End Get
Set(ByVal value As Integer)
If validI(value) AndAlso value <> _i Then
_i = value
If _editing Then Return
OnPropertyChanged(New PropertyChangedEventArgs("I"))
Else
SetPropertyMessage("I", "Not in range")
ItemMessage = "Value incorrect"
End If
End Set
End Property
Public Property S() As String
Get
Return _s
End Get
Set(ByVal value As String)
If validS(_s) AndAlso value <> _s Then
_s = value
If _editing Then Return
OnPropertyChanged(New PropertyChangedEventArgs("S"))
End If
End Set
End Property
' Additional Properties
<System.ComponentModel.Browsable(False)> _
Public ReadOnly Property HasChanges() As Boolean
Get
Return _hasChanges
End Get
End Property
<System.ComponentModel.Browsable(False)> _
Public ReadOnly Property HasErrors() As Boolean
Get
Return _hasErrors
End Get
End Property
' Constructors
Public Sub New()
initPmsgs()
End Sub
Public Sub New(ByVal i As Integer, ByVal s As String)
If validI(i) AndAlso validS(s) Then
_i = i
_s = s
_ii = i
_si = s
initPmsgs()
Else
Throw New ArgumentException("Invalid value")
End If
End Sub
' Data validation
Private Function validI(ByVal i As Integer) As Boolean
Return i >= 10 AndAlso i <= 100
End Function
Private Function validS(ByVal s As String) As Boolean
Return True
End Function
' IdataErrorInfo methods, properties
Private Sub initPmsgs()
_propertyMessages.Add("I", String.Empty)
_propertyMessages.Add("S", String.Empty)
End Sub
Private Sub clearMsgs()
_propertyMessages("I") = String.Empty
_propertyMessages("S") = String.Empty
_itemMessage = String.Empty
_hasErrors = False
End Sub
Private Sub SetPropertyMessage(ByVal propertyName As String, ByVal message _
As String)
If _propertyMessages(propertyName) Is Nothing Then Return
_propertyMessages(propertyName) = message
_hasErrors = True
End Sub
Private Function GetPropertyMessage(ByVal propertyName As String) As String
Return _propertyMessages(propertyName)
End Function
Private Property ItemMessage()
Get
Return _itemMessage
End Get
Set(ByVal value)
If value = _itemMessage Then Return
End Set
End Property
' PropertyChanged Event
Public Event PropertyChanged(ByVal sender As Object, ByVal e As _
System.ComponentModel.PropertyChangedEventArgs) Implements _
System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Protected Sub OnPropertyChanged(ByVal e As _
System.ComponentModel.PropertyChangedEventArgs)
_hasChanges = True
RaiseEvent PropertyChanged(Me, e)
End Sub
' IEditableObject Methods
Public Sub BeginEdit() Implements _
System.ComponentModel.IEditableObject.BeginEdit
Debug.WriteLine("BeginEdit")
_editing = True
_io = _i
_so = _s
End Sub
Public Sub CancelEdit() Implements _
System.ComponentModel.IEditableObject.CancelEdit
Debug.WriteLine("CancelEdit")
If _editing Then
_i = _io
_s = _so
End If
_editing = False
End Sub
Public Sub EndEdit() Implements _
System.ComponentModel.IEditableObject.EndEdit
Debug.WriteLine("EndEdit")
If _editing Then
_editing = False
If _i <> _io Then
OnPropertyChanged(New PropertyChangedEventArgs("I"))
End If
If _s <> _so Then
OnPropertyChanged(New PropertyChangedEventArgs("S"))
End If
End If
End Sub
' IDataErrorInfo
<System.ComponentModel.Browsable(False)> _
Public ReadOnly Property [Error]() As String Implements _
System.ComponentModel.IDataErrorInfo.Error
Get
Return ItemMessage
End Get
End Property
<System.ComponentModel.Browsable(False)> _
Default Public ReadOnly Property Item(ByVal columnName As String) As String _
Implements System.ComponentModel.IDataErrorInfo.Item
Get
Return _propertyMessages(columnName)
End Get
End Property
' Get DataGridView Display Columns
Public Shared Function GetViewColumns(ByVal names As String()) As _
DataGridViewColumn()
Dim col1 As New DataGridViewTextBoxColumn()
col1.DisplayIndex = 0
col1.HeaderText = "I"
col1.Name = "I"
col1.ValueType = GetType(Integer)
col1.DataPropertyName = "I"
Dim col2 As New DataGridViewTextBoxColumn()
col2.DisplayIndex = 1
col2.HeaderText = "S"
col2.Name = "S"
col2.ValueType = GetType(String)
col2.DataPropertyName = "S"
Dim allColumns As DataGridViewColumn() = {col1, col2}
If names Is Nothing OrElse names.Length = 0 Then
Return allColumns
End If
Dim returnColumsList As New List(Of DataGridViewColumn)
For Each dgvc In allColumns
If names.Contains(dgvc.Name) Then returnColumsList.Add(dgvc)
Next
Return returnColumsList.ToArray()
End Function
End Class ' mc Dann haben wir eine Collection-Klasse von BindableCollection abgeleitet
' Collection of mc Objects
Public Class MCCollection
Inherits BindableCollection(Of mc)
Public ReadOnly Property HasErrors() As Boolean
Get
For Each mc1 In Me.Items
If mc1.HasErrors Then Return True
Next
End Get
End Property
End Class Und hier eine kleine Anwendung (Form hat ein DGV, einige Buttons und zwei ListBoxen):
Public Class Form1
Dim mcc As New MCCollection
Dim bs As New BindingSource
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles MyBase.Load
' Daten anlegen
mcc.Add(New mc(33, "def"))
mcc.Add(New mc(19, "gdef"))
mcc.Add(New mc(77, "pdef"))
mcc.Add(New mc(10, "adef"))
mcc.Add(New mc(17, "fdef"))
' Init DataGridView
' AutoGenerate Columns noting Browsable Attribute
DataGridView1.AutoGenerateColumns = True
' Use more specific column declarations from the mc object itself
'DataGridView1.AutoGenerateColumns = false
'DataGridView1.Columns.AddRange(mc.GetViewColumns())
' Init DataBinding
bs.DataSource = mcc
DataGridView1.DataSource = bs
' Bind ListBoxes to two columns
ListBox1.DisplayMember = "I"
ListBox1.DataSource = bs
ListBox2.DisplayMember = "S"
ListBox2.DataSource = bs
End Sub
Private _i = 55
Private _s = "55"
' AddNew
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles Button1.Click
Dim nmc As mc = bs.AddNew()
_i += 1
nmc.I = _i
nmc.S = _i.ToString()
End Sub
' Change item(2)
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles Button2.Click
_i += 1
mcc(2).I = _i
mcc(2).S = _i.ToString()
End Sub
' Find
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles Button3.Click
If DataGridView1.SortedColumn.Name = "S" Then
Dim i As Integer = bs.Find(mcc.SortProperty, FindArgument.Text)
If i > -1 Then
bs.Position = i
If Not DataGridView1.CurrentRow.Displayed Then
DataGridView1.FirstDisplayedScrollingRowIndex = i
End If
Return
End If
End If
MsgBox("Sorry, not found")
End Sub
End Class (Da ist noch so ein Schmankerl oder zwei dabei).
Es ist wesentlich einfacher eine DataTable zu verwenden (oder Linq2Sql, EF usw.)
________
Alle Angaben ohne Gewähr. Keine Haftung für Vorschläge, Tipps oder sonstige Hilfe, falls es schiefgeht, nur Zeit verschwendet oder man sonst nicht zufrieden ist |