承载 ComboBox 控件的 DataGridColumnStyle (VB.NET)

来源:互联网 发布:蜡笔同步软件注册 编辑:程序博客网 时间:2024/05/17 22:54
承载 ComboBox 控件的 DataGridColumnStyle (VB.NET)

重写ComboBox类

Imports System.Windows.Forms

Public Class AutoCompleteComboBox
    
Inherits ComboBox
    
Public Sub New()
        
MyBase.New()
    
End Sub


    
Private mResetOnClear As Boolean = False
    
Protected Overrides Sub RefreshItem(ByVal index As Integer)
        
MyBase.RefreshItem(index)
    
End Sub


    
Protected Overrides Sub SetItemsCore(ByVal items As System.Collections.IList)
        
MyBase.SetItemsCore(items)
    
End Sub


    
Public Shadows Sub KeyPress(ByVal sender As ObjectByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
        
Dim intIndex As Integer
        
Dim strEntry As String

        
If Char.IsControl(e.KeyChar) Then
            
If MyBase.SelectionStart <= 1 Then
                
If mResetOnClear Then
                    
MyBase.SelectedIndex = 0
                    
MyBase.SelectAll()
                
Else
                    
MyBase.Text = String.Empty
                    
MyBase.SelectedIndex = -1
                
End If
                e.Handled 
= True
                
Exit Sub
            
End If
            
If MyBase.SelectionLength = 0 Then
                strEntry 
= MyBase.Text.Substring(0MyBase.Text.Length - 1)
            
Else
                strEntry 
= MyBase.Text.Substring(0MyBase.SelectionStart - 1)
            
End If
        
ElseIf (Not Char.IsLetterOrDigit(e.KeyChar)) And (Not Char.IsWhiteSpace(e.KeyChar)) Then  '< 32 Or KeyAscii > 127 Then
            Exit Sub
        
Else
            
If MyBase.SelectionLength = 0 Then
                strEntry 
= UCase(MyBase.Text & e.KeyChar)
            
Else
                strEntry 
= MyBase.Text.Substring(0MyBase.SelectionStart) & e.KeyChar
            
End If
        
End If

        
MyBase.DroppedDown = Char.IsLetterOrDigit(e.KeyChar)

        intIndex 
= MyBase.FindString(strEntry)
        
If intIndex <> -1 Then
            
MyBase.SelectedIndex = intIndex
            
MyBase.SelectionStart = strEntry.Length
            
MyBase.SelectionLength = MyBase.Text.Length - MyBase.SelectionStart
        
End If

        e.Handled 
= True
        
Exit Sub
    
End Sub


    
Public Property ResetOnClear() As Boolean
        
Get
            
Return mResetOnClear
        
End Get
        
Set(ByVal Value As Boolean)
            mResetOnClear 
= Value
        
End Set
    
End Property

End Class

实现类

Option Strict On
Option Explicit On 
Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Data

Public Class DataGridComboBox
    
Inherits AutoCompleteComboBox
    
Public Sub New()
        
MyBase.New()
    
End Sub

    
Public isInEditOrNavigateMode As Boolean = True

End Class


Public Class DataGridComboBoxColumnStyle
    
Inherits DataGridColumnStyle

    
Private xMargin As Integer = 2
    
Private yMargin As Integer = 1
    
Private Combo As DataGridComboBox
    
Private _DisplayMember As String
    
Private _ValueMember As String

    
Private OldVal As String = String.Empty
    
Private InEdit As Boolean = False

    
Public Sub New(ByRef DataSource As DataTable, _
                   
ByVal DisplayMember As Integer, _
                   
ByVal ValueMember As Integer)

        Combo 
= New DataGridComboBox
        _DisplayMember 
= DataSource.Columns.Item(index:=DisplayMember).ToString
        _ValueMember 
= DataSource.Columns.Item(index:=ValueMember).ToString

        
With Combo
            .Visible 
= False
            .DataSource 
= DataSource
            .DisplayMember 
= _DisplayMember
            .ValueMember 
= _ValueMember
        
End With
    
End Sub


    
Public Sub New(ByRef DataSource As DataTable, _
                   
ByVal DisplayMember As String, _
                   
ByVal ValueMember As String)

        Combo 
= New DataGridComboBox
        
With Combo
            .Visible 
= False
            .DataSource 
= DataSource
            .DisplayMember 
= DisplayMember
            .ValueMember 
= ValueMember
        
End With

    
End Sub


    
Protected Overloads Overrides Sub Abort(ByVal RowNum As Integer)
        Debug.WriteLine(
"Abort()")
        RollBack()
        HideComboBox()
        EndEdit()
    
End Sub


    
Protected Overloads Overrides Function Commit(ByVal DataSource As CurrencyManager, _
                                                  
ByVal RowNum As IntegerAs Boolean
        HideComboBox()
        
If Not InEdit Then
            
Return True
        
End If

        
Try
            
Dim Value As Object = Combo.SelectedValue
            
If NullText.Equals(Value) Then
                Value 
= Convert.DBNull
            
End If
            SetColumnValueAtRow(DataSource, RowNum, Value)
        
Catch e As Exception
            RollBack()
            
Return False
        
End Try
        EndEdit()
        
Return True
    
End Function


    
Protected Overloads Overrides Sub ConcedeFocus()
        Combo.Visible 
= False
    
End Sub


    
Protected Overloads Overrides Sub Edit(ByVal Source As CurrencyManager, _
                                           
ByVal Rownum As Integer, _
                                           
ByVal Bounds As Rectangle, _
                                           
ByVal [ReadOnlyAs Boolean, _
                                           
ByVal InstantText As String, _
                                           
ByVal CellIsVisible As Boolean)

        Combo.Text 
= String.Empty

        
Dim OriginalBounds As Rectangle = Bounds

        OldVal 
= Combo.Text

        
If CellIsVisible Then
            Bounds.Offset(xMargin, yMargin)
            Bounds.Width 
-= xMargin * 2
            Bounds.Height 
-= yMargin
            Combo.Bounds 
= Bounds
            Combo.Visible 
= True
        
Else
            Combo.Bounds 
= OriginalBounds
            Combo.Visible 
= False
        
End If

        Combo.SelectedValue 
= GetText(GetColumnValueAtRow(Source, Rownum))

        
If Not InstantText Is Nothing Then
            Combo.SelectedValue 
= InstantText
        
End If

        Combo.RightToLeft 
= Me.DataGridTableStyle.DataGrid.RightToLeft
        Combo.Focus()

        
If InstantText Is Nothing Then
            Combo.SelectAll()
        
Else
            
Dim [EndAs Integer = Combo.Text.Length
            Combo.Select([
End], 0)
        
End If

        
If Combo.Visible Then
            DataGridTableStyle.DataGrid.Invalidate(OriginalBounds)
        
End If

        InEdit 
= True

    
End Sub


    
Protected Overloads Overrides Function GetMinimumHeight() As Integer
        
Return Combo.PreferredHeight + yMargin
    
End Function


    
Protected Overloads Overrides Function GetPreferredHeight(ByVal g As Graphics, _
                                                              
ByVal Value As ObjectAs Integer
        Debug.WriteLine(
"GetPreferredHeight()")
        
Dim NewLineIndex As Integer = 0
        
Dim NewLines As Integer = 0
        
Dim ValueString As String = Me.GetText(Value)
        
Do
            
While NewLineIndex <> -1
                NewLineIndex 
= ValueString.IndexOf("r/n", NewLineIndex + 1)
                NewLines 
+= 1
            
End While
        
Loop

        
Return FontHeight * NewLines + yMargin
    
End Function


    
Protected Overloads Overrides Function GetPreferredSize(ByVal g As Graphics, _
                                                            
ByVal Value As ObjectAs Size
        
Dim Extents As Size = Size.Ceiling(g.MeasureString(GetText(Value), _
                                           
Me.DataGridTableStyle.DataGrid.Font))
        Extents.Width 
+= xMargin * 2 + DataGridTableGridLineWidth
        Extents.Height 
+= yMargin
        
Return Extents
    
End Function


    
Protected Overloads Overrides Sub Paint(ByVal g As Graphics, _
                                            
ByVal Bounds As Rectangle, _
                                            
ByVal Source As CurrencyManager, _
                                            
ByVal RowNum As Integer)
        Paint(g, Bounds, Source, RowNum, 
False)
    
End Sub


    
Protected Overloads Overrides Sub Paint(ByVal g As Graphics, _
                                            
ByVal Bounds As Rectangle, _
                                            
ByVal Source As CurrencyManager, _
                                            
ByVal RowNum As Integer, _
                                            
ByVal AlignToRight As Boolean)
        
Dim Text As String = GetText(GetColumnValueAtRow(Source, RowNum))
        PaintText(g, Bounds, Text, AlignToRight)
    
End Sub


    
Protected Overloads Sub Paint(ByVal g As Graphics, _
                                  
ByVal Bounds As Rectangle, _
                                  
ByVal Source As CurrencyManager, _
                                  
ByVal RowNum As Integer, _
                                  
ByVal BackBrush As Brush, _
                                  
ByVal ForeBrush As Brush, _
                                  
ByVal AlignToRight As Boolean)

        
Dim Text As String = GetText(GetColumnValueAtRow(Source, RowNum))
        PaintText(g, Bounds, Text, BackBrush, ForeBrush, AlignToRight)
    
End Sub


    
Protected Overloads Overrides Sub SetDataGridInColumn(ByVal Value As DataGrid)
        
MyBase.SetDataGridInColumn(Value)
        
If Not (Combo.Parent Is Value) Then
            
If Not (Combo.Parent Is NothingThen
                Combo.Parent.Controls.Remove(Combo)
            
End If
        
End If

        
If Not (Value Is NothingThen Value.Controls.Add(Combo)
    
End Sub


    
Protected Overloads Overrides Sub UpdateUI(ByVal Source As CurrencyManager, _
                                               
ByVal RowNum As IntegerByVal InstantText As String)
        Combo.Text 
= GetText(GetColumnValueAtRow(Source, RowNum))
        
If Not (InstantText Is NothingThen
            Combo.Text 
= InstantText
        
End If
    
End Sub


    
Private ReadOnly Property DataGridTableGridLineWidth() As Integer
        
Get
            
If Me.DataGridTableStyle.GridLineStyle = DataGridLineStyle.Solid Then
                
Return 1
            
Else
                
Return 0
            
End If
        
End Get
    
End Property


    
Private Sub EndEdit()
        InEdit 
= False
        Invalidate()
    
End Sub


    
Private Function GetText(ByVal Value As ObjectAs String
        
If Value Is System.DBNull.Value Then Return NullText

        
If Not Value Is Nothing Then
            
Return Value.ToString
        
Else
            
Return String.Empty
        
End If

    
End Function


    
Private Sub HideComboBox()
        
If Combo.Focused Then
            
Me.DataGridTableStyle.DataGrid.Focus()
        
End If
        Combo.Visible 
= False
    
End Sub


    
Private Sub RollBack()
        Combo.Text 
= OldVal
    
End Sub


    
Private Sub PaintText(ByVal g As Graphics, _
                          
ByVal Bounds As Rectangle, _
                          
ByVal Text As String, _
                          
ByVal AlignToRight As Boolean)

        
Dim BackBrush As Brush = New SolidBrush(Me.DataGridTableStyle.BackColor)
        
Dim ForeBrush As Brush = New SolidBrush(Me.DataGridTableStyle.ForeColor)
        PaintText(g, Bounds, Text, BackBrush, ForeBrush, AlignToRight)
    
End Sub


    
Private Sub PaintText(ByVal g As Graphics, _
                          
ByVal TextBounds As Rectangle, _
                          
ByVal Text As String, _
                          
ByVal BackBrush As Brush, _
                          
ByVal ForeBrush As Brush, _
                          
ByVal AlignToRight As Boolean)

        
Dim Rect As Rectangle = TextBounds
        
Dim RectF As RectangleF = RectF.op_Implicit(Rect) ' Convert to RectangleF
        Dim Format As StringFormat = New StringFormat

        
If AlignToRight Then
            
Format.FormatFlags = StringFormatFlags.DirectionRightToLeft
        
End If

        
Select Case Me.Alignment
            
Case Is = HorizontalAlignment.Left
                
Format.Alignment = StringAlignment.Near
            
Case Is = HorizontalAlignment.Right
                
Format.Alignment = StringAlignment.Far
            
Case Is = HorizontalAlignment.Center
                
Format.Alignment = StringAlignment.Center
        
End Select

        
Format.FormatFlags = Format.FormatFlags Or StringFormatFlags.NoWrap
        g.FillRectangle(Brush:
=BackBrush, Rect:=Rect)

        Rect.Offset(
0, yMargin)
        Rect.Height 
-= yMargin
        g.DrawString(Text, 
Me.DataGridTableStyle.DataGrid.Font, ForeBrush, RectF, Format)
        
Format.Dispose()

    
End Sub


    
Public ReadOnly Property ComboBox() As ComboBox
        
Get
            
Return Combo
        
End Get
    
End Property

End Class

测试代码

Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        InitForm(DataGrid1)
        
Dim namesDataTable As DataTable
        namesDataTable 
= New DataTable("NamesTable")

        namesDataTable.Columns.Add(
"Name"GetType(String))
        namesDataTable.Columns.Add(
"Sex"GetType(String))

        
Dim namesDataSet As DataSet = New DataSet
        namesDataSet.Tables.Add(namesDataTable)
        DataGrid1.DataSource 
= namesDataSet
        DataGrid1.DataMember 
= "NamesTable"

        AddGridStyle(DataGrid1)
        AddData(namesDataTable)

    
End Sub


    
Private Sub AddGridStyle(ByRef myGrid As DataGrid)
        
Dim myGridStyle As DataGridTableStyle = New DataGridTableStyle
        myGridStyle.MappingName 
= "NamesTable"

        
Dim nameColumnStyle As DataGridTextBoxColumn = New DataGridTextBoxColumn
        nameColumnStyle.MappingName 
= "Name"
        nameColumnStyle.HeaderText 
= "Name"
        myGridStyle.GridColumnStyles.Add(nameColumnStyle)

        
Dim mydt As DataTable
        mydt 
= New DataTable
        mydt.Columns.Add(
"id"GetType(String))
        mydt.Columns.Add(
"text"GetType(String))

        
Dim newRowW As DataRow
        newRowW 
= mydt.NewRow()
        newRowW(
0= "0"
        newRowW(
1= ""
        
Dim newRowM As DataRow
        newRowM 
= mydt.NewRow()
        newRowM(
0= "1"
        newRowM(
1= ""
        mydt.Rows.Add(newRowM)
        mydt.Rows.Add(newRowW)

        
Dim comboxColumnStyle As New DataGridComboBoxColumnStyle(mydt, 11)
        comboxColumnStyle.MappingName 
= "Sex"
        comboxColumnStyle.HeaderText 
= "Sex"
        comboxColumnStyle.Width 
= 100
        myGridStyle.GridColumnStyles.Add(comboxColumnStyle)

        myGrid.TableStyles.Add(myGridStyle)
    
End Sub


    
Private Sub AddData(ByRef namesDataTable As DataTable)
        
Dim dRow As DataRow = namesDataTable.NewRow()
        dRow(
"Name"= "小站"
        dRow(
"Sex"= ""
        namesDataTable.Rows.Add(dRow)

        dRow 
= namesDataTable.NewRow()
        dRow(
"Name"= "小李"
        dRow(
"Sex"= ""
        namesDataTable.Rows.Add(dRow)

        dRow 
= namesDataTable.NewRow()
        dRow(
"Name"= "小吴"
        dRow(
"Sex"= ""
        namesDataTable.Rows.Add(dRow)

        namesDataTable.AcceptChanges()
    
End Sub


    
Private Sub InitForm(ByRef myGrid As DataGrid)
        myGrid.TabStop 
= True
        myGrid.TabIndex 
= 1
    
End Sub
原创粉丝点击