【发布时间】:2014-12-09 22:37:42
【问题描述】:
我似乎找不到可行的解决方案。
我有一个基于 DataGridViewTextboxColumn 的自定义 datagridview 单元格。我正在为此使用 VB 2005。
我正在尝试实现一个设计时属性,我可以使用该属性来存储列中的单元格使用的 SQL 语句。每行的查找相同,但返回的值不同。
我有一个版本,它要求我在 CellFormatting 和 RowsAdded 事件期间设置语句,但我想这样做,所以我所要做的就是提供一个 SQL 语句(即 Select JobName From JobList where JobNo = {0})作为列类中的属性。我想绑定单元格并使用它获得的值作为语句的替换值。我无法让 SQL 语句属性持久化(正确的词?)
我的部分问题是我不确定该属性是否应该放在自定义 COLUMN 或自定义 CELL 定义中。我一直在尝试将属性添加到列中,这似乎是合乎逻辑的,因为我希望在单元格中为每个实例使用相同的值,而不必在每次触发单元格格式事件时设置语句值。
我找到并尝试了这些属性:
<Browsable(True), _
EditorBrowsable(EditorBrowsableState.Always), _
Category("Data"), _
Description("The SQL Query to use for lookup. Make sure it will work with string.format"), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
Public Property ScalarSQLStatement() As String
End Property
它不起作用。我可以在列编辑器中输入值,但如果我退出编辑器并返回,属性将重置为默认值。
编辑----
我为 DataGridTextboxCell 创建了子类并将其放入其中:
Imports System.ComponentModel
Public Class DataGridViewScalarValue2TextboxCell
Inherits DataGridViewTextBoxCell
Private _scalarStatement As String = String.Empty
Private _ReturnValue As String = String.Empty
Private _LookupValue As Object
Public Property LookupValue() As Object
Get
Return _LookupValue
End Get
Set(ByVal value As Object)
_LookupValue = value
End Set
End Property
Public Sub New()
Me._LookupValue = Nothing
If Me.OwningColumn Is Nothing Then Return
Me.ScalarStatement = CType(Me.OwningColumn, DataGridViewScalarValue2TextboxColumn).ScalarSQLStatement
End Sub
Public Property ScalarStatement() As String
Get
Return _scalarStatement
End Get
Set(ByVal Value As String)
_scalarStatement = Value
End Set
End Property
' Override the Clone method so that the Enabled property is copied.
Public Overrides Function Clone() As Object
Dim Cell As DataGridViewScalarValue2TextboxCell = CType(MyBase.Clone(), _
DataGridViewScalarValue2TextboxCell)
Cell._scalarStatement = Me._scalarStatement
Return Cell
End Function
Protected Overrides Function GetFormattedValue(ByVal value As Object, _
ByVal rowIndex As Integer, _
ByRef cellStyle As DataGridViewCellStyle, _
ByVal valueTypeConverter As TypeConverter, _
ByVal formattedValueTypeConverter As TypeConverter, _
ByVal context As DataGridViewDataErrorContexts) As Object
If _LookupValue <> value Then
_LookupValue = value
GetReturnValueFromLookupValue()
End If
Return MyBase.GetFormattedValue(_ReturnValue, rowIndex, cellStyle, _
valueTypeConverter, formattedValueTypeConverter, context)
End Function
Protected Overrides Sub Paint(ByVal graphics As Graphics, _
ByVal clipBounds As Rectangle, _
ByVal cellBounds As Rectangle, _
ByVal rowIndex As Integer, _
ByVal cellState As DataGridViewElementStates, _
ByVal value As Object, _
ByVal formattedValue As Object, _
ByVal errorText As String, _
ByVal cellStyle As DataGridViewCellStyle, _
ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
ByVal paintParts As DataGridViewPaintParts)
If value IsNot Nothing AndAlso _
(TypeOf value Is String AndAlso Not String.IsNullOrEmpty(value)) OrElse _
(TypeOf value Is Integer AndAlso Integer.TryParse(value, Nothing)) OrElse _
(TypeOf value Is Decimal AndAlso Decimal.TryParse(value, 0)) OrElse _
(TypeOf value Is Date) AndAlso IsDate(value) Then
_LookupValue = value
GetReturnValueFromLookupValue()
Else
_ReturnValue = String.Empty
End If
MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, _
_ReturnValue, errorText, cellStyle, advancedBorderStyle, paintParts)
End Sub
Private Sub GetReturnValueFromLookupValue()
If _LookupValue Is Nothing _
Or OwningColumn Is Nothing _
Or String.IsNullOrEmpty(_scalarStatement) Then
_ReturnValue = Nothing
Return
End If
Using conn As New SqlClient.SqlConnection(ConnUtils.MyGCPTableConnectionString)
conn.Open()
Dim cmd As SqlClient.SqlCommand = conn.CreateCommand
With cmd
.CommandText = String.Format(_scalarStatement, _LookupValue)
.CommandType = CommandType.Text
Dim objResult = .ExecuteScalar
If objResult IsNot Nothing Then
_ReturnValue = objResult
End If
End With
conn.Close()
End Using
End Sub
Public Overloads Property Value() As Object
Get
Return _ReturnValue
End Get
Set(ByVal value)
If TypeOf value Is Integer AndAlso value > 0 Then
If _LookupValue <> value Then
_LookupValue = value
GetReturnValueFromLookupValue()
End If
End If
End Set
End Property
End Class
我对 DataGridViewTextboxColumn 类做了同样的事情。在我的原始帖子中引用了它的主要属性(用于此用途)。这个子类里面有这段代码:
Imports System.ComponentModel
Public Class DataGridViewScalarValue2TextboxColumn
Inherits DataGridViewTextBoxColumn
Public Sub New()
Me.CellTemplate = New DataGridViewScalarValue2TextboxCell()
End Sub
'' Fields...
Private _scalarSQLStatement As String = String.Empty
<Browsable(True), _
EditorBrowsable(EditorBrowsableState.Always), _
Category("Data"), _
Description("The SQL Query to use for lookup. Make sure it will work with string.format"), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
Public Property ScalarSQLStatement() As String
Get
Return _scalarSQLStatement
End Get
Set(ByVal Value As String)
_scalarSQLStatement = Value
End Set
End Property
在表单中,我使用 CellFormatting 和 RowsAdded 事件,如下所示:
Private Sub dgvCustomCellTypes_CellFormatting(ByVal sender As Object, ByVal e As .DataGridViewCellFormattingEventArgs) Handles dgvCustomCellTypes.CellFormatting
If e.ColumnIndex = colHaulID2.Index Then
Dim dgvr As DataGridViewRow = CType(sender, DataGridView).Rows(e.RowIndex)
Dim HaulCell As DataGridViewScalarValue2TextboxCell = CType(dgvr.Cells(colHaulID2.Index), DataGridViewScalarValue2TextboxCell)
HaulCell.ScalarStatement = colHaulID2.ScalarSQLStatement
End If
End Sub
Private Sub dgvCustomCellTypes_RowsAdded(ByVal sender As Object, ByVal e As DataGridViewRowsAddedEventArgs) Handles dgvCustomCellTypes.RowsAdded
For i As Integer = e.RowIndex To e.RowCount - 1
Dim dgvr As DataGridViewRow = CType(sender, DataGridView).Rows(i)
Dim HaulCell As DataGridViewScalarValue2TextboxCell = CType(dgvr.Cells(colHaulID2.Index), DataGridViewScalarValue2TextboxCell)
HaulCell.ScalarStatement = colHaulID2.ScalarSQLStatement
Next
End Sub
并将其添加到表单初始化中:
colHaulID2.ScalarSQLStatement = "Select CompanyName From HaulCompany Where HaulID = {0}"
该列是数据绑定的,并在那里获取其查找值。它工作正常,但不是我正在寻找的解决方案。
我正在尝试重写单元格/列,以便我可以在设计时使用列编辑器将 SQL 语句添加到列中,并依靠数据绑定值来提供查找键。
在我看来,唯一阻止我实现目标的就是在设计时关闭列编辑器后让控件保存它的 SQL 语句。或者在我重新打开列编辑器时防止它被清除。我不确定发生了什么。但我确信有一个解决方案。我在持久性方面做了一些尝试,包括我发现的一个类似 VB6 的属性包示例。我忽略了将属性保存到磁盘。似乎应该有一种方法可以让应用程序处理此任务。到目前为止,没有什么对我有用
结束编辑
任何帮助将不胜感激。
谢谢。
马歇尔
【问题讨论】:
标签: sql-server vb.net datagridview custom-controls