Hi,
Here is a column style that locks a column on the datagrid. It is
still under development. basically if you set the locked property to true
it places a panel over the datagrid that has the locked column drawn on it.
Currently it only will lock the first column.
Imports System.Drawing.Drawing2D
Public Class ColoredGridColumn
Inherits DataGridTextBoxColumn
Dim mForeColor As Color = Color.Black
Dim mBackColor As Color = Color.White
Dim WithEvents mctrl As DblBufferPanel
Dim WithEvents dg As DataGrid
Dim pt As New Point
Dim bPanelOnly As Boolean = False
Dim cm As CurrencyManager
Dim ar As Boolean
Private Class DblBufferPanel
Inherits Panel
Public Sub New()
Me.SetStyle(ControlStyles.DoubleBuffer, True)
End Sub
End Class
Public Property ForeColor() As Color
Get
Return mForeColor
End Get
Set(ByVal Value As Color)
mForeColor = Value
End Set
End Property
Public Property BackColor() As Color
Get
Return mBackColor
End Get
Set(ByVal Value As Color)
mBackColor = Value
End Set
End Property
Public Property Locked() As Boolean
Get
Return Not mctrl Is Nothing
End Get
Set(ByVal Value As Boolean)
If Value = False Then
mctrl = Nothing
Else
mctrl = New DblBufferPanel
End If
End Set
End Property
Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics,
ByVal bounds As System.Drawing.Rectangle, ByVal source As
System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer, ByVal
backBrush As System.Drawing.Brush, ByVal foreBrush As System.Drawing.Brush,
ByVal alignToRight As Boolean)
Dim brFore As Brush
Dim brBack As Brush
Dim cFore As Color
Dim cBack As Color
Static bPainted As Boolean = False
If Not bPainted And Not (mctrl Is Nothing) Then
dg = Me.DataGridTableStyle.DataGrid
dg.Parent.Controls.Add(mctrl)
MovePanel()
mctrl.BringToFront()
pt = dg.GetCellBounds(0, 0).Location
If TypeOf dg.DataSource Is DataTable Then
AddHandler DirectCast(dg.DataSource, DataTable).DefaultView.ListChanged,
AddressOf dv_ListChanged
ElseIf TypeOf dg.DataSource Is DataView Then
AddHandler DirectCast(dg.DataSource, DataView).ListChanged, AddressOf
dv_ListChanged
End If
End If
cm = source
ar = alignToRight
bPainted = True
If Me.DataGridTableStyle.DataGrid.IsSelected(rowNum) Then
cFore = Me.DataGridTableStyle.SelectionForeColor
cBack = Me.DataGridTableStyle.SelectionBackColor
Else
cFore = ForeColor
cBack = BackColor
End If
brBack = New LinearGradientBrush(bounds, cBack, Color.White, 90, False)
brFore = New SolidBrush(cFore)
Dim bl As New Blend
bl.Factors = New Single() {0.0F, 0.1F, 0.5F, 0.7F, 0.7F, 0.5F, 0.3F, 0.2F,
0}
bl.Positions = New Single() {0, 0.1F, 0.2F, 0.5F, 0.6F, 0.7F, 0.8F, 0.9F,
1.0F}
DirectCast(brBack, LinearGradientBrush).Blend = bl
If Not bPanelOnly Then
MyBase.Paint(g, bounds, source, rowNum, brBack, brFore, alignToRight)
End If
If Not (mctrl Is Nothing) Then
' if there is another control to draw on move the bounds to the right edge
if htere is not then it will ignore that directive right? yesgot oitf the
control
'mctrl.BackgroundImage = bm
PaintRow(mctrl.CreateGraphics, bounds, rowNum)
End If
If Me.GetColumnValueAtRow(source, rowNum).ToString = "Davolio" Then
Me.DataGridTableStyle.DataGrid.Select(rowNum)
End If
End Sub
Public Shadows Sub BeginUpdate()
MyBase.BeginUpdate()
End Sub
Public Shadows Sub EndUpdate()
MyBase.EndUpdate()
End Sub
Protected Overloads Overrides Sub Edit(ByVal source As
System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer, ByVal bounds
As System.Drawing.Rectangle, ByVal [readOnly] As Boolean, ByVal instantText
As String, ByVal cellIsVisible As Boolean)
MyBase.Edit(source, rowNum, bounds, [readOnly], instantText, cellIsVisible)
MyBase.TextBox.ForeColor = ForeColor()
MyBase.TextBox.BackColor = BackColor
End Sub
Public Sub New()
End Sub
Private Sub dg_Scroll(ByVal sender As Object, ByVal e As System.EventArgs)
Handles dg.Scroll
Trace.WriteLine("Scroll")
RedrawPanel()
End Sub
Private Sub MovePanel()
mctrl.Location = New Point(dg.Left + dg.RowHeaderWidth + 2, dg.Top + 21)
Dim intFactor As Integer = SystemInformation.HorizontalScrollBarHeight
For Each ctrl As Control In Me.DataGridTableStyle.DataGrid.Controls
If TypeOf ctrl Is HScrollBar Then
If Not DirectCast(ctrl, HScrollBar).Visible Then intFactor = 0
End If
Next
mctrl.Height = dg.Height - 21 - intFactor - 2
End Sub
Private Sub dg_Move(ByVal sender As Object, ByVal e As System.EventArgs)
Handles dg.Move
MovePanel()
End Sub
Private Sub PreparePanel()
Dim sf As New StringFormat
sf.LineAlignment = StringAlignment.Center
Dim rDraw As New RectangleF(0, 0, Me.Width, 20)
Dim g As Graphics = mctrl.CreateGraphics
g.Clear(mctrl.BackColor)
Try
g.DrawString(Me.HeaderText, dg.Font, Brushes.Black, rDraw, sf)
ControlPaint.DrawBorder3D(g, _
New Rectangle(0, 0, Me.Width, 19), Border3DStyle.RaisedInner)
Catch
End Try
End Sub
Private Sub dv_ListChanged(ByVal sender As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)
'PreparePanel()
RedrawPanel()
End Sub
Private Sub dg_VisibleChanged(ByVal sender As Object, ByVal e As
System.EventArgs) Handles dg.VisibleChanged
Try
mctrl.Visible = dg.Visible
Catch ex As Exception
End Try
End Sub
Private Sub dg_SizeChanged(ByVal sender As Object, ByVal e As
System.EventArgs) Handles dg.SizeChanged
MovePanel()
RedrawPanel()
End Sub
Private Sub RedrawPanel()
Static oldTop As Integer = 0
If Not mctrl Is Nothing And dg.VisibleRowCount > 0 Then
Application.DoEvents()
Dim hti As DataGrid.HitTestInfo = dg.HitTest(pt)
Dim newRow As Integer = hti.Row
Trace.WriteLine(String.Format("First Row {0} Visible rows {1}", hti.Row,
dg.VisibleRowCount))
oldTop = newRow
bPanelOnly = True
For x As Integer = oldTop To oldTop + dg.VisibleRowCount - 1
If x < cm.Count Then
Trace.WriteLine(String.Format("Drawing Row {0} {1}", x, dg.GetCellBounds(x,
dg.FirstVisibleColumn)))
Paint(Nothing, dg.GetCellBounds(x, dg.FirstVisibleColumn), _
cm, x, Nothing, Nothing, ar)
End If
Next
bPanelOnly = False
End If
End Sub
Private Sub dg_Resize(ByVal sender As Object, ByVal e As System.EventArgs)
Handles dg.Resize
MovePanel()
End Sub
Private Sub mctrl_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles mctrl.Paint
Dim sf As New StringFormat
sf.LineAlignment = StringAlignment.Center
Dim rDraw As New RectangleF(0, 0, Me.Width, 20)
Dim g As Graphics = e.Graphics
g.Clear(mctrl.BackColor)
Try
g.DrawString(Me.HeaderText, dg.Font, Brushes.Black, rDraw, sf)
ControlPaint.DrawBorder3D(g, _
New Rectangle(0, 0, Me.Width, 19), Border3DStyle.RaisedInner)
Debug.WriteLine("Panel Paint")
Dim hti As DataGrid.HitTestInfo = dg.HitTest(pt)
Dim newRow As Integer = hti.Row
Dim oldTop As Integer
Trace.WriteLine(String.Format("First Row {0} Visible rows {1}", hti.Row,
dg.VisibleRowCount))
oldTop = newRow
bPanelOnly = True
For x As Integer = oldTop To oldTop + dg.VisibleRowCount - 1
If x < cm.Count Then
Trace.WriteLine(String.Format("Drawing Row {0} {1}", x, dg.GetCellBounds(x,
dg.FirstVisibleColumn)))
Paint(Nothing, dg.GetCellBounds(x, dg.FirstVisibleColumn), _
cm, x, Nothing, Nothing, ar)
End If
Next
Catch
End Try
End Sub
Private Sub PaintRow(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal
rownum As Integer)
Dim brFore As Brush
Dim brBack As Brush
Dim cFore As Color
Dim cBack As Color
Dim bounds2 As New Rectangle(0, bounds.Y - 21, bounds.Width, bounds.Height)
If Me.DataGridTableStyle.DataGrid.IsSelected(rownum) Then
cFore = Me.DataGridTableStyle.SelectionForeColor
cBack = Me.DataGridTableStyle.SelectionBackColor
Else
cFore = ForeColor
cBack = BackColor
End If
brBack = New LinearGradientBrush(bounds, cBack, Color.White, 90, False)
brFore = New SolidBrush(cFore)
Dim bl As New Blend
bl.Factors = New Single() {0.0F, 0.1F, 0.5F, 0.7F, 0.7F, 0.5F, 0.3F, 0.2F,
0}
bl.Positions = New Single() {0, 0.1F, 0.2F, 0.5F, 0.6F, 0.7F, 0.8F, 0.9F,
1.0F}
DirectCast(brBack, LinearGradientBrush).Blend = bl
If mctrl.Width <> Me.Width Then mctrl.Width = Me.Width
MyBase.Paint(g, bounds2, cm, rownum, _
brBack, brFore, ar)
If rownum = cm.Count - 1 Then
Dim br As New SolidBrush(Me.DataGridTableStyle.DataGrid.BackgroundColor)
g.FillRectangle(br, 0, bounds2.Bottom + 1, mctrl.Width, _
mctrl.Height - bounds2.Bottom - 1)
End If
End Sub
End Class
Ken
-------------------------------
"Agnes" wrote in message
news:
[email protected]...
I understand it is impossible, but still curious to know "Can I freeze
several column in the datagrid, the user can only scroll the first 3 columns
(not verical), for the rest of the coulumn, it is freeze.