vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Blitzschnelles Erstellen von grafischen Diagrammen!  
 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:  11.737 

Summer-Special bei Tools & Components!
Gute Laune Sommer bei Tools & Components
Top Summer-Special - Sparen Sie teilweise bis zu 120,- EUR
Alle sev-Entwicklerkomponenten und Komplettpakete jetzt bis zu 25% reduziert!
zum Beispiel:
  • Developer CD nur 479,20 EUR statt 599,- EUR
  • sevDTA 3.0 nur 224,30 EUR statt 299,- EUR
  •  
  • vb@rchiv   Vol.6 nur 20,00 EUR statt 24,95 EUR
  • sevCoolbar 3.0 nur 55,20 EUR statt 69,- EUR
  • - Werbung -Und viele weitere Angebote           Aktionspreise nur für kurze Zeit gültig

    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 11.737 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