vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
NEU! sevCoolbar 3.0 - Professionelle Toolbars im modernen Design!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   RSS-Feeds  | Newsletter  | Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2017
 
zurück
Rubrik: .NET   |   VB-Versionen: VB2005, VB200804.05.09
ListView um einen Suchdialog erweitern

In vielen Anwendungen ist es selbstverständlich, das man in einem Inhalt suchen kann. Das ListView-Control bietet jedoch leider keine Suche, lässt sich aber mit folgendem Tipp nachrüsten.

Autor:  Carsten StuplichBewertung:     [ Jetzt bewerten ]Views:  12.042 

Der hier Erstelle Suchdialog berücksichtigt dabei, ob in dem ListView-Control ein Multi-Row-Select möglich ist oder nicht.

Als erstes erstellen wir ein Formular mit dem Namen frmFindInListView, das folgende Controls enthält:

ControlName
LabelLabel1
LabelLabel2
TextBoxtxtSearchText
ComboBoxcombSearchColumn
CheckBoxchkNonCaseSensetive
CheckBoxchkOnlyWholeWord
CheckBoxchkSearchTextIsRegEx
ButtonOK_Button
ButtonCancel_Button

Der Dialog sieht dann wie folgt aus:

In das Formular kopiert man nun folgenden Sourcecode:

Imports System.Windows.Forms
Imports System.Text.RegularExpressions
 
Public Class frmFindInListView
 
  Private objListview As ListView
  Private objMainForm As Form
  Private bolIngnoreColumnsWithZeroWidth As Boolean
 
  ' Wird benötigt umd bei einfach Auswhal festzusellen, das schon mal gesucht wurde
  Private bSearched As Boolean = False
  Private iLastFoundRowIndex As Integer = 0, iLastCheckedRowIndex As Integer
  Private bTextFound As Boolean = False
  Private Sub OK_Button_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles OK_Button.Click
 
    ' Alle Texte in LisView selektieren, in dem der Text vorkommt
    Dim i As Integer, y As Integer, iSearchStart As Integer
    Dim bShowMsg As Boolean = True
    Dim bExit As Boolean = False
 
    ' Wenn bei letzer Suche (Single-Select in ListView) die letzte 
    ' Zeile erreicht wurde, dann Suche von neu beginnen
    If objListview.MultiSelect = False AndAlso _
      iLastCheckedRowIndex = objListview.Items.Count - 1 Then
 
      bSearched = False
      iLastFoundRowIndex = 0
      iLastCheckedRowIndex = 0
    End If
 
    ' Startzeile für Suche festlegen (jenachdem ob Liste Multi-Select erlaub oder nicht)
    If objListview.MultiSelect = True Then
      iSearchStart = 0
 
      ' alle Selektionen bei Multi-Select entfernen
      Dim oListViewItem As ListViewItem
      For Each oListViewItem In objListview.SelectedItems
        oListViewItem.Selected = False
      Next 
    Else
      If bSearched = False Then
        ' Bei ersten Mal in erster Zeilen beginnen
        iSearchStart = 0
      Else
        iSearchStart = iLastFoundRowIndex + 1
      End If
    End If
 
    bSearched = True
    If combSearchColumn.SelectedIndex <> combSearchColumn.Items.Count - 1 Then
      ' Suche über eine Spalte
      For i = iSearchStart To objListview.Items.Count - 1
        iLastCheckedRowIndex = i
        Try
          If ContainsPlus(objListview.Items(i).SubItems(combSearchColumn.SelectedIndex).Text, _
            txtSearchText.Text, Not chkNonCaseSensetive.Checked, chkOnlyWholeWord.Checked, _
            chkSearchTextIsRegEx.Checked) = True Then
 
            bTextFound = True
            iLastFoundRowIndex = i
            objListview.Select()
            objListview.Items(i).Selected = True
            If objListview.MultiSelect = False Then Exit For
          End If
        Catch ex As Exception
          If chkSearchTextIsRegEx.Checked = True Then 
            MessageBox.Show("Fehler beim Auswerten des Regulären Ausdrucks!" & _
            Environment.NewLine & Environment.NewLine & _
            "Fehler:" & Environment.NewLine & ex.Message, _
            "Fehler bei Regulären-Ausdruck", MessageBoxButtons.OK, MessageBoxIcon.Error)
          End If
          bShowMsg = False
          ExitFor
        End Try
 
      Next i
    Else
 
      ' Suche über alle Spalten
      For i = iSearchStart To objListview.Items.Count - 1
        iLastCheckedRowIndex = i
 
        For y = 0 To objListview.Columns.Count - 1
          'Versteckte Spalten überspringen Option entsprechend eingestellt
          If bolIngnoreColumnsWithZeroWidth = True AndAlso _
            objListview.Columns(y).Width = 0 Then Continue For
 
          Try
            If ContainsPlus(objListview.Items(i).SubItems(y).Text, txtSearchText.Text, _
              Not chkNonCaseSensetive.Checked, chkOnlyWholeWord.Checked, _
              chkSearchTextIsRegEx.Checked) = True Then
 
              bTextFound = True
              iLastFoundRowIndex = i
              objListview.Select()
              objListview.Items(i).Selected = True
              If objListview.MultiSelect = False Then bExit = True
              ' Wenn eine Zeile Markiert wurde, müssen folgende Spalten 
              ' nicht mehr geprüft werden
              Exit For 
            End If
          Catch ex As Exception
            If chkSearchTextIsRegEx.Checked = True Then 
              MessageBox.Show("Fehler beim Auswerten des Regulären Ausdrucks!" & _
              Environment.NewLine & Environment.NewLine & _
              "Fehler:" & Environment.NewLine & ex.Message, _
              "Fehler bei Regulären-Ausdruck", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End If
            bExit = True: Exit For
          End Try
        Next y
        If bExit Then Exit For 
      Next i
    End If
 
    ' Wenn Text nicht gefunde wurde, dann Meldung
    If bShowMsg Then
      If bTextFound = False Then
        MessageBox.Show("Der Text konnte mit den angegebenen Suchkriterien nicht " & _
          "in der Liste gefunden werden!", "Suche", MessageBoxButtons.OK, MessageBoxIcon.Information)
        Exit Sub
      End If
    End If
 
    ' Bei Multi-Select ListView Dialog schließen, bei Single-Select Liste scrollen
    If objListview.MultiSelect = True Then
      Me.DialogResult = System.Windows.Forms.DialogResult.OK
      Me.Close()
    Else
      If objListview.SelectedItems.Count <> 0 Then 
        objListview.EnsureVisible(objListview.SelectedItems(0).Index)
      End If
    End If
 
    ' Hauptformular in den Vordergrund bringen, damit Selektion sichtbar wird
    objMainForm.BringToFront()
  End Sub
  Private Sub Cancel_Button_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Cancel_Button.Click
 
    Me.DialogResult = System.Windows.Forms.DialogResult.Cancel
    Me.Close()
  End Sub
  Private Sub frmFindInListView_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
 
    txtSearchText.Select()
    If objListview.MultiSelect = True Then 
      OK_Button.Text = "OK"
    Else
      OK_Button.Text = "Weitersuchen"
    End If
  End Sub
  Public Overloads Sub Show(ByVal oListview As ListView, _
    ByVal oMainForm As Form, _
    Optional ByVal bIngnoreColumnsWithZeroWidth As Boolean = False)
 
    ' Alle Spalten des Listviews in Auswahl aufnehmen
    Dim i As Integer
 
    objListview = oListview
    objMainForm = oMainForm
    bolIngnoreColumnsWithZeroWidth = bIngnoreColumnsWithZeroWidth
 
    For i = 0 To objListview.Columns.Count - 1
      If bIngnoreColumnsWithZeroWidth = True AndAlso _
        objListview.Columns(i).Width = 0 Then Continue For
      combSearchColumn.Items.Add(objListview.Columns(i).Text)
    Next i
    combSearchColumn.Items.Add("-- ALLE SPALTEN --")
    combSearchColumn.SelectedIndex = combSearchColumn.Items.Count - 1
 
    MyBase.Show(objListview)
  End Sub
  Public Overloads Sub ShowDialog(ByVal oListview As ListView, _
    ByVal oMainForm As Form, _
    Optional ByVal bIngnoreColumnsWithZeroWidth As Boolean = False)
 
    ' ShowDialog muss verwendet werden, damit Fokus wieder richtig 
    ' gesetzt wird, wenn Dialog beendet wird
    Show(oListview, oMainForm)
  End Sub
  ''' <summary>
  ''' Diese Funktion prüft, ob eine Bestimmte Zeichenfolge oder ein Wort in einem Text vorkommt
  ''' </summary>
  ''' <param name="WholeText">Kompletter Text in dem geprüft werden soll</param>
  ''' <param name="ContainText">Zu suchender Text</param>
  ''' <param name="bIgnoreCase">Wenn True, wird Gross-/Kleinschreibung ignoriert</param>
  ''' <param name="bOnlyWholeWords">Wenn True, muss 'ContainText' als komplettes Wort 
  ''' vorhanden sein und nicht nur in einer Zeichenkette vorkommen.</param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Private Function ContainsPlus(ByVal WholeText As String, _
    ByVal ContainText As String, _
    Optional ByVal bIgnoreCase As Boolean = True, _
    Optional ByVal bOnlyWholeWords As Boolean = False, _
    Optional ByVal bContainTextIsRegularExpression As Boolean = False) As String
 
    Dim tmpContainText As String = ""
 
    ' Wenn ContainText keine Regulären Ausdrücke enthält, dann ContainText in 
    ' ASCI-Codes für REGEX umsetzen, damit z.B. ] nicht als Regulärer-Ausdruck 
    ' interpretiert wird, sonstern als Text 
    If bContainTextIsRegularExpression = False Then
      Dim byteArray() As Byte
      Dim hexNumbers As System.Text.StringBuilder = New System.Text.StringBuilder
 
      byteArray = System.Text.ASCIIEncoding.ASCII.GetBytes(ContainText)
 
      For i As Integer = 0 To byteArray.Length - 1
        hexNumbers.Append("\x" & byteArray(i).ToString("x"))
      Next
      tmpContainText = hexNumbers.ToString
 
    Else
      tmpContainText = ContainText
    End If
 
    ' Patterns für ganzens Worte setzen (Wenn nur auf komplette Wörter geprüft werden soll)
    If bOnlyWholeWords = True Then tmpContainText = tmpContainText & "\b"
 
    If bIgnoreCase = True Then
      Return Regex.IsMatch(WholeText, tmpContainText, RegexOptions.IgnoreCase)
    Else
      Return Regex.IsMatch(WholeText, tmpContainText)
    End If
 
  End Functiony
  Private Sub txtSearchText_TextChanged(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles txtSearchText.TextChanged
 
    bTextFound = False ' Zurück setzen das Text gefunden wurde
  End Sub
  Private Sub combSearchColumn_SelectedIndexChanged(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles combSearchColumn.SelectedIndexChanged
 
    bTextFound = False ' Zurück setzen das Text gefunden wurde
  End Sub
  Private Sub chkNonCaseSensetive_CheckedChanged(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles chkNonCaseSensetive.CheckedChanged
 
    bTextFound = False ' Zurück setzen das Text gefunden wurde
  End Sub
  Private Sub chkOnlyWholeWord_CheckedChanged(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles chkOnlyWholeWord.CheckedChanged
 
    bTextFound = False ' Zurück setzen das Text gefunden wurde
  End Sub
End Class

Erläuterungen zum Code:

  • Damit man eine beliebige ListView an den Suchdialog binden kann, habe ich die Show-Methode „überladen“ und erwartet als Parameter die Übergabe des ListViews sowie das Objekt des Hauptformulars (wird benötigt wenn die Liste kein MultiRow-Select erlaubt, um den Fokus auf das Hauptformular zu setzen.)
     
  • Da die String-Methode „Contains“ des Frameworks nicht alle meine Anforderungen abdeckte, hab ich die Funktion „ContainsPlus“ erstellt.
Diese prüft per Regulären-Ausdruck, ob ein Text in einem anderen vorkommt und erlaubt u.a. auch die Übergabe eines Regulären-Ausdrucks in unserem Suchdialog.

Weitere Funktion des „ListViewEx“:
Im Beispielprojekt zu diesem Workshop ist ein Projekt enthalten, das das ListView Control abgesehen vom Suchdialog noch um folgende Funktionen erweitert:

  • SaveSelectedKeys
    (Speichert die Keys der selektierten Zeilen in einer Collection - Können Sie dazu verwenden, um die Selektion vor neu Laden der Liste zu speichern und nach neu Laden der Liste per „RestoreSelectedKey“ wieder die „alten Einträge“ zu selektieren)
     
  • RestoreSelectedKeys
    (Stellt die Selektion von Listview.Items wieder her)
     
  • ContainsKey
    (Liefert True zurück, wenn der übergeben Key in der Listview gefunden wird)
     
  • SelectByKey
    (Sucht nach dem übergebenen Key und selektiert den Eintrag wenn dieser gefunden wird)
     
  • SetRowForeColor
    (Setzt die Schriftfarbe für eine ganze Zeile)
     
  • SetRowBackColor
    (Setzt die Hintergrundfarbe für eine ganze Zeile)
     
  • SaveToFile
    (Speichert den Inhalt der ListView in eine Textdatei)
     
  • StopRefresh
    (Aufruf von "BeginUpdate" und "SuspendLayout")
     
  • ResumeRefresh
    (Aufruf von "ResumeLayout" und "EndUpdate"
     
  • DeleteRowsThatDontContainsString
    (Löschte alle Zeilen, die einen bestimmten Texte in Spalte X nicht enthalten)

1. ListViewEx verwenden

1.1 Control „ListViewEx“ in Ihr Projekt einbinden
Kopieren Sie die Datei „ListviewEx.dll“ an eine beliebige Stelle z.B. unter: „C:\Programme\Microsoft Visual Studio 9.0\Common7\IDE“.

Darauf fügen Sie die DLL der Toolbox in Visual-Studio hinzu.
Ab sofort können Sie das das Control wie die normale ListView Ihrer Form per Drag & Drop hinzufügen.

1.2 Aufruf des Suchdialogs
Wenn Sie bereits wie in Punkt 1.1 beschrieben das ListViewEx als Control verwenden, können Sie den Suchdialog wie folgt aufrufen:

  • Fügen Sie Ihrem Formular ein

    Imports ListViewExtended

    hinzu und verwenden folgende Zeilen (z.B. bei Key-Down Event von Strg+F), um den Suchdialog einzublenden:

    Dim ofrmFindInListView As frmFindInListView = New frmFindInListView
    ofrmFindInListView.Show(ListViewEx1, Me)

    Daraufhin erscheint der Suchdialog, der mit allen verfügbaren Spalten Ihres Listviews gefüllt ist.

     Download ListViewEx (115 KB)

  • Dieser Workshop wurde bereits 12.042 mal aufgerufen.

    Über diesen Workshop im Forum diskutieren
    Haben Sie Fragen oder Anregungen zu diesem Workshop, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

    Neue Diskussion eröffnen

    nach obenzurück


    Anzeige

    Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Workshops finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6
    (einschl. Beispielprojekt!)

    Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
    - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
    - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
    Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
     
       

    Druckansicht Druckansicht Copyright ©2000-2017 vb@rchiv Dieter Otter
    Alle Rechte vorbehalten.
    Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

    Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel