65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在网格列(UltraWinGrid)中实现增量搜索

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.61/5 (8投票s)

2005 年 2 月 10 日

CPOL

6分钟阅读

viewsIcon

100102

downloadIcon

1614

本文旨在展示如何通过双击 UltraWinGrid 列来实现增量搜索。

引言

此代码为您提供了一个问题的解决方案:如何在 WinGrid 列中双击实现增量搜索?也许编码存在一些不足,但我相信它会给您一个如何完成此过程的思路。

注释

此新版本包括一个用于清除筛选器/增量搜索文本框的按钮。之前的版本,当鼠标光标离开列时会清除/删除此元素。搜索功能已得到改进,冗余代码已删除,现在增量搜索框仅在鼠标光标位于列标题上时才添加。使用方法 ElementWithMouseCapture 进行代码优化。

当增量搜索或过滤数据的文本框放置在某一列上并进行滚动时,此文本框会覆盖单元格。此问题已在此版本中修复。

Sample screenshot

概览(背景)

使用 Infragistics.Win.UIElement 对象,您可以验证鼠标光标所在的界面对象的类型。此对象还具有 GetContext 方法,该方法返回对象的主 UI。如果您编写代码,您会发现此对象是 TextUIElement。您还会看到 ColumnHeaderSortIndicatorUIElement 对象存在于对象列中。我检测光标所在的对象是否是列,并通过代码向其添加 UltraTextEditor 对象。此对象有一个用于过滤的按钮(只有当用户单击此按钮时才执行过滤),一个用于移除过滤的按钮,以及 TextChanged 事件中的代码用于增量搜索。由于在分组列特征启用时,网格的工作方式不同,因此也已考虑在内。如果您检查代码,您会发现它验证网格行是否属于某个组(使用 UltraGridGroupByRowChildBands)。我编写的代码以两种方式工作:用户可以选择进行过滤或进行增量搜索(隐式)。

本文还展示了如何显示列上的工具提示以及如何将数据绑定到文本框以在记录之间导航。

代码概述

为了正确执行,需要以下命名空间。

Imports System.IO
Imports System.String
Imports System.Data
Imports System.Data.SqlClient
Imports Infragistics.Win.UltraWinGrid
Imports Infragistics.Win
Imports Infragistics.Shared

使用以下变量,并且必须声明。

#Region " V A R I A B L E S "
    Dim bindman As BindingManagerBase 'For bind the text boxes to the row's grid.
    'A local data set. You need modify the connection string
    Dim localdataset As New System.Data.DataSet 
    Dim _activeColumn As String 
    Dim ui As Infragistics.Win.UIElement 
    Dim aColumnHeader As Infragistics.Win.UltraWinGrid.ColumnHeader
    Dim nRowByGroupOriginal As Long
#End Region

Load 事件中,执行与 SQL 数据库的连接。您需要修改连接字符串以指向有效的数据库和表才能正确执行。网格具有 Outlook 样式视图。此事件的最后一行代码展示了如何向网格中的单元格添加图像,在本例中,是第一个单元格。

Private Sub Itemsforupdate_Load(ByVal sender As System.Object, _ 
         ByVal e As System.EventArgs) Handles MyBase.Load
    Me.grdItems.DisplayLayout.ViewStyleBand = _ 
            Infragistics.Win.UltraWinGrid.ViewStyleBand.OutlookGroupBy

    Dim sqlAdapter As New SqlDataAdapter( _
       "SELECT * FROM customers", _
       New SqlConnection("Initial Catalog=northwind;Data Source= _
                                  (local);Integrated Security=SSPI;"))
    sqlAdapter.Fill(localdataset, "customers")
    Me.UltraTextEditor1.DataBindings.Add("text", _
                         localdataset.Tables("customers"), "customerid")
    Me.UltraTextEditor2.DataBindings.Add("text", _
                         localdataset.Tables("customers"), "contactname")
    bindman = Me.BindingContext(localdataset.Tables("customers"))
    Me.grdItems.DataSource = localdataset.Tables("customers")
    Me.grdItems.Rows(0).Cells(0).Appearance.Image = _ 
          System.Drawing.Image.FromFile(Application.StartupPath & "\clock.png")
End Sub

Paint 事件中的下一段代码为窗体设置了酷炫的填充。棒极了!

Private Sub Itemsforupdate_Paint(ByVal sender As Object,  _
          ByVal e As System.Windows.Forms.PaintEventArgs) _
          Handles MyBase.Paint
    Dim FillBrush As New Drawing2D.LinearGradientBrush(ClientRectangle, _
    Color.Khaki, Color.WhiteSmoke, _
    Drawing2D.LinearGradientMode.ForwardDiagonal)
    e.Graphics.FillRectangle(FillBrush, ClientRectangle)
    FillBrush.Dispose()
End Sub

MouseEnterElement 事件中,我检查鼠标光标所在的控件。这是必要的,因为增量文本框是添加到标题或列上的。此事件的第一行代码对 UI 元素进行类型转换,并将其转换为 ColumnHeader 元素(控件)。注释掉的代码允许在鼠标进入列标题时添加增量搜索的文本框。此事件展示了如何在每列上显示工具提示。当您有许多列且尺寸较小时,此功能非常有用。

以下代码已修订并更新!
Private Sub grdItems_MouseEnterElement(ByVal sender As Object, _
          ByVal e As Infragistics.Win.UIElementEventArgs) _
          Handles grdItems.MouseEnterElement
     aColumnHeader = _
         CType(e.Element.GetContext( _
         GetType(Infragistics.Win.UltraWinGrid.ColumnHeader)), _
         Infragistics.Win.UltraWinGrid.ColumnHeader)
     If Not aColumnHeader Is Nothing And TypeOf e.Element Is HeaderUIElement Then
         _activeColumn = aColumnHeader.Column.Key
         MyToolTip.Active = True
         MyToolTip.SetToolTip(CType(sender, System.Windows.Forms.Control), _
              aColumnHeader.Column.Key)
         MyTextSearchBox.Size = _
             New Size(aColumnHeader.SizeResolved.Width, _
             aColumnHeader.SizeResolved.Height)
         ui = e.Element
         aColumnHeader.Band.ColHeaderLines = 1
         Exit Sub
     End If
 End Sub

MouseLeaveElement 事件中的代码会移除工具提示的文本。

以下代码已修订并更新!
Private Sub grdItems_MouseLeaveElement(ByVal sender As Object, _
         ByVal e As Infragistics.Win.UIElementEventArgs) _
         Handles grdItems.MouseLeaveElement
     Dim ui As Infragistics.Win.UIElement
     ui = e.Element
     If TypeOf e.Element Is HeaderUIElement Then
          MyToolTip.SetToolTip(sender, String.Empty)
     End If
 End Sub

过滤网格行的代码位于文本框控件的 EditorButtonClick 事件中。

以下代码已修订并更新!
Private Sub MyTextSearchBox_EditorButtonClick(ByVal sender As Object, _ 
            ByVal e As Infragistics.Win.UltraWinEditors.EditorButtonEventArgs) _
            Handles MyTextSearchBox.EditorButtonClick
  Dim band As UltraGridBand = Me.grdItems.DisplayLayout.Bands(0)
  Select Case e.Button.Key.ToLower
    Case "clearfilter"
      RemoveFilter()
    Case Else
      band.Override.AllowRowFiltering = DefaultableBoolean.True
      band.Override.RowFilterMode = RowFilterMode.AllRowsInBand
      band.ColumnFilters(_activeColumn).FilterConditions.Add( _
                                        FilterComparisionOperator.Like, _ 
                                        "*" & MyTextSearchBox.Text.Trim & "*")
   End Select
End Sub

增量搜索的代码位于文本框控件的 TextChanged 事件中。当网格的行按列分组或具有子带(如 Outlook 样式)时,代码是不同的。

以下代码已修订和更改!
Private Sub MyTextSearchBox_TextChanged(ByVal sender As Object, _
                 ByVal e As System.EventArgs) Handles MyTextSearchBox.TextChanged
  If MyTextSearchBox.Text <> "" Then
  Dim myCellValue As String
  Static gRow As UltraGridRow
  Dim nRow As Long
  Me.grdItems.SuspendLayout()
  grdItems.BeginUpdate()
  Me.grdItems.DisplayLayout.Override.MaxSelectedCells = 1
  Me.grdItems.DisplayLayout.Override.SelectTypeCell = SelectType.Single
  If (Not TypeOf grdItems.ActiveRow Is _
       Infragistics.Win.UltraWinGrid.UltraGridGroupByRow _ 
       And IsNothing(grdItems.Rows(nRowByGroupOriginal).ChildBands)) Then
  For Each gRow In Me.grdItems.Rows
    grdItems.ActiveRow = gRow
    myCellValue = grdItems.ActiveRow.Cells(_activeColumn).Text
    If [String].CompareOrdinal(myCellValue.ToLower, _
                LCase(Me.MyTextSearchBox.Text.Trim)) > 0 Then
      gRow.Cells(_activeColumn).Activate()
      gRow.Cells(_activeColumn).Selected = True
      Exit For
    End If
  Next
  Else
    For Each gRow In grdItems.Rows(nRowByGroupOriginal).ChildBands(0).Rows
    myCellValue = _
       grdItems.Rows(nRowByGroupOriginal).ChildBands(0).Rows( _
                                    gRow.Index).Cells(_activeColumn).Text
    If [String].CompareOrdinal(myCellValue.ToLower, LCase( _
                                    Me.MyTextSearchBox.Text.Trim)) > 0 Then
      grdItems.Rows(nRowByGroupOriginal).ChildBands(0).Rows( _
                                    gRow.Index).Cells(_activeColumn).Activate()
      grdItems.Rows(nRowByGroupOriginal).ChildBands(0).Rows( _
                                    gRow.Index).Cells(_activeColumn).Selected =_
                                    True
      Exit For
    End If
    Next
  End If
  Me.grdItems.ResumeLayout()
  grdItems.EndUpdate()
  End If
End Sub

以下代码用于强制网格滚动到第一行(当执行筛选或增量搜索时)。

Private Sub grdItems_BeforeRowActivate(ByVal sender As Object, _
          ByVal e As Infragistics.Win.UltraWinGrid.RowEventArgs) _
          Handles grdItems.BeforeRowActivate
    ' determine which row should be the top row
    Dim rowTop As UltraGridRow
    If e.Row.Band.Index = 0 Then
        rowTop = e.Row
    Else
        rowTop = e.Row.ParentRow
    End If
    With grdItems.DisplayLayout
       ' scroll the row into the RowScrollRegion
       .RowScrollRegions(0).ScrollRowIntoView(rowTop)
       ' turn off display refresh during update
       grdItems.BeginUpdate()
       ' scroll the top row to the top
       Do Until .RowScrollRegions(0).VisibleRows(0).Row Is rowTop
          .RowScrollRegions(0).Scroll(RowScrollAction.LineDown)
       Loop
       ' turn display refresh back on
       grdItems.EndUpdate()
    End With
End Sub

DoubleClick 事件中添加用于增量搜索的控件。当用户双击 columnheader 元素(边框)时,会添加文本框。主要上下文元素是 TextUIElement,但当用户点击时,网格默认按列标题对列进行排序。因此,当用户点击 TextUIElement 时,我没有添加文本框。

以下代码已修订和更新!
Private Sub grdItems_DoubleClick(ByVal sender As Object, _
                                       ByVal e As System.EventArgs) _
                                       Handles grdItems.DoubleClick
  If Not IsNothing(ui) Then
    If _activeColumn <> "" And _
       TypeOf ui.ControlElement.ElementWithMouseCapture Is HeaderUIElement Then
      grdItems.DisplayLayout.Bands(0).Columns(_activeColumn).SortIndicator _
                                     = SortIndicator.None
      grdItems.PerformAction(UltraGridAction.FirstRowInBand)
      ' If  Then
      MyTextSearchBox.Location = ui.Rect.Location
      ui.Control.Controls.Add(MyTextSearchBox)
      MyTextSearchBox.Visible = True
      MyTextSearchBox.Focus()
      'End If
    End If
  End If
End Sub

当网格具有分组(如 Outlook 样式)时,以下代码至关重要。获取当前展开的组。

Private Sub grdItems_AfterRowExpanded(ByVal sender As Object, _
           ByVal e As Infragistics.Win.UltraWinGrid.RowEventArgs) _
           Handles grdItems.AfterRowExpanded
    nRowByGroupOriginal = e.Row.Index
End Sub

为了移除过滤或增量搜索的文本框,我使用了 Sub RemoveFilter。当用户点击 ClearFilter 按钮(第二个按钮)时,将调用此 Sub

新增代码
Private Sub RemoveFilter()
        Dim band As UltraGridBand = Me.grdItems.DisplayLayout.Bands(0)
        band.Override.AllowRowFiltering = DefaultableBoolean.False
        band.ColumnFilters(_activeColumn).FilterConditions.Clear()
        MyToolTip.SetToolTip(ui.Control, String.Empty)
        MyTextSearchBox.Visible = False
        ui.Control.Controls.Clear()
        _activeColumn = ""
End Sub

为避免增量搜索文本框放置在网格上的任何位置,我编写了这些新事件

Private Sub grdItems_BeforeRowRegionScroll(ByVal sender As Object, _
        ByVal e As Infragistics.Win.UltraWinGrid.BeforeRowRegionScrollEventArgs) _
        Handles grdItems.BeforeRowRegionScroll
 grdItems.SuspendLayout()
 If Not IsNothing(ui) Then
     If TypeOf ui.ControlElement.LastElementEntered Is _
         Infragistics.Win.UltraWinScrollBar.ScrollArrowUIElement Or _
         TypeOf ui.ControlElement.ElementWithMouseCapture Is _
         Infragistics.Win.UltraWinScrollBar.ScrollBarUIElement Then
         ui.Control.Controls.Clear()
     End If
 End If
End Sub
Private Sub grdItems_BeforeColRegionScroll(ByVal sender As Object, _
     ByVal e As Infragistics.Win.UltraWinGrid.BeforeColRegionScrollEventArgs) _
     Handles grdItems.BeforeColRegionScroll
 grdItems.SuspendLayout()
 If Not IsNothing(ui) Then
     If TypeOf ui.ControlElement.LastElementEntered Is _
         Infragistics.Win.UltraWinScrollBar.ScrollArrowUIElement Or _
         TypeOf ui.ControlElement.ElementWithMouseCapture Is _
         Infragistics.Win.UltraWinScrollBar.ScrollBarUIElement Then
         ui.Control.Controls.Clear()
     End If
 End If
End Sub
Private Sub grdItems_AfterColRegionScroll(ByVal sender As Object, _
          ByVal e As Infragistics.Win.UltraWinGrid.ColScrollRegionEventArgs) _
          Handles grdItems.AfterColRegionScroll
        grdItems.ResumeLayout()
End Sub
Private Sub grdItems_AfterRowRegionScroll(ByVal sender As Object, _
          ByVal e As Infragistics.Win.UltraWinGrid.RowScrollRegionEventArgs) _
          Handles grdItems.AfterRowRegionScroll
        grdItems.ResumeLayout()
End Sub

摘要

在此代码中,您可以看到(版本 2.0,2005/02/10,1652

  • 如何在运行时将控件添加到具有焦点(或鼠标悬停)的对象上。
  • 如何为每列添加工具提示。
  • 如何按特定列过滤行。
  • 如何在列中的数据上进行增量搜索。
  • 如何使用 CType()GetContext() 函数。
  • 如何使用 SQL Server 2000 连接到数据库:sqlConnectionsqlDataAdapterDataSets
  • 如何向特定单元格添加图像。
  • 如何验证网格是否具有行组(如 Outlook 样式)。
  • 如何滚动网格以使筛选条件或增量搜索的条件文本中指示的元素可见。
  • 如何使用 filterconditions 过滤数据。
  • 如何使用 CompareTo 函数比较两个字符串。
  • 如何使用 Infragistics.Win.UIElement 检测特定控件或元素:HeaderUIElementSortIndicatorUIElementTextUIElementElementWithMouseCapture 等。
  • 如何对窗体应用 LinearGradient 填充,以获得炫酷效果。

版本 2.0

  • 添加一个按钮以移除用于过滤或增量搜索的文本框。
  • 实现列/行 ScrollRegion 之前的/之后的事件,以便在用户滚动时移除文本框。这可以避免控件在单元格上方“放置”(仅视觉上)。
  • 改进了 DoubleClick 事件中的代码。使用 ElementWithMouseCapture,双击事件仅在 ui.ControlElement 类型为 HeaderUIElement 时执行。
  • 使用 CompareOrdinal 方法而不是 CompareTo 方法进行文本搜索。
  • 修复了一个未处理的异常错误;当用户在窗体启动后立即滚动,而没有将鼠标光标移动到列上方时(未创建 ui 元素)。

Notice

此代码假定您正在使用 Infragistics UltraWinGrid,并且是此出色组件套件的授权用户。您可以从此处下载 NetAdvantage 2004 vol 3 的试用版。此代码仅用于演示目的。您还需要连接到 SQL Server 2000 Northwind 数据库。

我希望此代码对您有用。从此处下载 NetAdvantage 2004 Vol 3 的试用版。

此致,

CFQüeb

© . All rights reserved.