我正在尝试使用 vb.net 从列表和数据表中转置可编辑 DataGridView。
因此,在 Datagridview1 转置可编辑(来自列表)中,结果为 Datagridview1 不可转置且不可编辑,而在 Datagridview2 转置可编辑(来自数据表)中,结果为 Datagridview4 不可转置且不可编辑。
我在 C# 编程语言中找到了@RezaAghaei(下面的链接)的答案,但我尝试使用编程语言 VB.NET 编写代码,方法中出现错误
Default Public Property Item(ByVal i As Integer) As Object
请指导我
谢谢
以下代码的结果来自上面的链接并转换为 vb.net
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Linq
Public Class RotatedListDataSource(Of T)
Inherits List(Of RotatedItem)
Public ReadOnly Property List As List(Of T)
Public Sub New(ByVal list As List(Of T))
Me.List = list
Me.AddRange(GetType(T).GetProperties().Select(Function(p) New RotatedItem(p.Name, list.Cast(Of Object)().ToArray(), p.PropertyType)))
End Sub
End Class
Public Class RotatedItem
Inherits CustomTypeDescriptor
Public ReadOnly Property PropertyName As String
Private data() As Object
Public ReadOnly Property Type As Type
Public Sub New(ByVal propertyName As String, ByVal data() As Object, ByVal type As Type)
Me.PropertyName = propertyName
Me.data = data
Me.Type = type
End Sub
Public Overrides Function GetProperties() As PropertyDescriptorCollection
Return Me.GetProperties(New Attribute() {})
End Function
Public Overrides Function GetProperties(ByVal attributes() As Attribute) As PropertyDescriptorCollection
Dim properties = New List(Of PropertyDescriptor)()
properties.Add(New PropertyNameProperty(New Attribute() {New BrowsableAttribute(False)}))
For i As Integer = 0 To data.Length - 1
properties.Add(New IndexProperty(i, GetType(Object), New Attribute() {}))
Next i
Return New PropertyDescriptorCollection(properties.ToArray())
End Function
Default Public Property Item(ByVal i As Integer) As Object
Get
'Error below line Overload resolution failed because no accessible 'GetValue' accepts this number of arguments.
Return data(i).GetType().GetProperty(PropertyName).GetValue(data(i))
End Get
Set(ByVal value As Object)
'Error below line Overload resolution failed because no accessible 'SetValue' accepts this number of arguments.
data(i).GetType().GetProperty(PropertyName).SetValue(data(i), Convert.ChangeType(value, Type))
End Set
End Property
End Class
Public Class IndexProperty
Inherits PropertyDescriptor
Private index As Integer
Private type As Type
Public Sub New(ByVal index As Integer, ByVal type As Type, ByVal attributes() As Attribute)
MyBase.New(index.ToString(), attributes)
Me.index = index
Me.type = type
End Sub
Public Overrides ReadOnly Property ComponentType As Type
Get
Return GetType(RotatedItem)
End Get
End Property
Public Overrides ReadOnly Property IsReadOnly As Boolean
Get
Return False
End Get
End Property
Public Overrides ReadOnly Property PropertyType As Type
Get
Return type
End Get
End Property
Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
Return False
End Function
Public Overrides Function GetValue(ByVal component As Object) As Object
Return DirectCast(component, RotatedItem)(index)
End Function
Public Overrides Sub ResetValue(ByVal component As Object)
End Sub
Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object)
DirectCast(component, RotatedItem)(index) = value
End Sub
Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
Return True
End Function
End Class
Public Class PropertyNameProperty
Inherits PropertyDescriptor
Public Sub New(ByVal attributes() As Attribute)
MyBase.New(NameOf(RotatedItem.PropertyName), attributes)
End Sub
Public Overrides ReadOnly Property ComponentType As Type
Get
Return GetType(RotatedItem)
End Get
End Property
Public Overrides ReadOnly Property IsReadOnly As Boolean
Get
Return True
End Get
End Property
Public Overrides ReadOnly Property PropertyType As Type
Get
Return GetType(String)
End Get
End Property
Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
Return False
End Function
Public Overrides Function GetValue(ByVal component As Object) As Object
Return DirectCast(component, RotatedItem).PropertyName
End Function
Public Overrides Sub ResetValue(ByVal component As Object)
End Sub
Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object)
End Sub
Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
Return True
End Function
End Class
Public Class Form1
Private Sub LISTEMP()
Dim Product As New List(Of Product)() From {
New Product() With {
.Codeproduct = "SHIRTA",
.Productname = "SHIRT WHITE",
.Size = "S",
.Qty = 1
},
New Product() With {
.Codeproduct = "SHIRTB",
.Productname = "SHIRT BLACK",
.Size = "M",
.Qty = 1
},
New Product() With {
.Codeproduct = "SHIRTC",
.Productname = "SHIRT YELLOW",
.Size = "L",
.Qty = 1
},
New Product() With {
.Codeproduct = "SHIRTD",
.Productname = "SHIRT GREEN",
.Size = "XL",
.Qty = 1
},
New Product() With {
.Codeproduct = "SHIRTE",
.Productname = "SHIRT YELLOW",
.Size = "2L",
.Qty = 1
}
}
DataGridView1.DataSource = Product.ToList()
End Sub
Private Sub datatableEMP()
Dim Product As New DataTable()
Product.Columns.Add("Codeproduct", GetType(String))
Product.Columns.Add("Productname", GetType(String))
Product.Columns.Add("Size", GetType(String))
Product.Columns.Add("Qty", GetType(Integer))
Product.Rows.Add("SHIRTA", "SHIRT WHITE", "S", 1)
Product.Rows.Add("SHIRTB", "SHIRT BLACK", "M", 1)
Product.Rows.Add("SHIRTC", "SHIRT YELLOW", "L", 1)
Product.Rows.Add("SHIRTD", "SHIRT GREEN", "XL", 1)
Product.Rows.Add("SHIRTE", "SHIRT YELLOW", "2L", 1)
DataGridView2.DataSource = Product
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LISTEMP()
datatableEMP()
End Sub
End Class
Public Class Product
Public Property Codeproduct As String
Public Property Productname As String
Public Property Size As String
Public Property Qty As Integer
End Class
我的代码的结果
想要的结果
Datagridview1 转置可编辑(来自列表)
代码产品 | 产品名称 | S | M | L | XL | 2L |
---|---|---|---|---|---|---|
希尔塔 | 衬衫白色 | 1 | ||||
衬衫 | 衬衫黑色 | 1 | ||||
衬衫 | 衬衫黄色 | 1 | ||||
衬衫 | 衬衫绿色 | 1 | ||||
衬衫 | 衬衫黄色 | 1 |
Datagridview2 转置可编辑(来自数据表)
代码产品 | 产品名称 | S | M | L | XL | 2L |
---|---|---|---|---|---|---|
希尔塔 | 衬衫白色 | 1 | ||||
衬衫 | 衬衫黑色 | 1 | ||||
衬衫 | 衬衫黄色 | 1 | ||||
衬衫 | 衬衫绿色 | 1 | ||||
衬衫 | 衬衫黄色 | 1 |
Datagridview3 结果未从 datagridview1 转置且不可编辑(来自列表)
代码产品 | 产品名称 | 尺寸 | 数量 |
---|---|---|---|
希尔塔 | 衬衫白色 | S | 1 |
衬衫 | 衬衫黑色 | M | 1 |
衬衫 | 衬衫黄色 | L | 1 |
衬衫 | 衬衫绿色 | XL | 1 |
衬衫 | 衬衫黄色 | 2L | 1 |
Datagridview4 结果来自 datagridview2(来自数据表)不可转置且不可编辑
代码产品 | 产品名称 | 尺寸 | 数量 |
---|---|---|---|
希尔塔 | 衬衫白色 | S | 1 |
衬衫 | 衬衫黑色 | M | 1 |
衬衫 | 衬衫黄色 | L | 1 |
衬衫 | 衬衫绿色 | XL | 1 |
衬衫 | 衬衫黄色 | 2L | 1 |
这是我的原始帖子的 VB 版本,它是用 C# 编写的。
主要课程
这些是在自定义类型描述符的帮助下实现原始列表中的旋转数据源的类:
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Linq
Public Class RotatedListDataSource(Of T)
Inherits List(Of RotatedItem)
Public ReadOnly Property List As List(Of T)
Public Sub New(ByVal list As List(Of T))
list = list
Me.AddRange(GetType(T).GetProperties() _
.Select(Function(p)
Return New RotatedItem(p.Name, list.Cast(Of Object)().ToArray(), p.PropertyType)
End Function))
End Sub
End Class
Public Class RotatedItem
Inherits CustomTypeDescriptor
Public ReadOnly Property PropertyName As String
Private data As Object()
Public ReadOnly Property Type As Type
Public Sub New(ByVal propertyName As String, ByVal data As Object(), ByVal type As Type)
Me.PropertyName = propertyName
Me.data = data
Me.Type = type
End Sub
Public Overrides Function GetProperties() As PropertyDescriptorCollection
Return Me.GetProperties(New Attribute() {})
End Function
Public Overrides Function GetProperties(ByVal attributes As Attribute()) As PropertyDescriptorCollection
Dim properties = New List(Of PropertyDescriptor)()
properties.Add(New PropertyNameProperty(New Attribute() {New BrowsableAttribute(False)}))
For i As Integer = 0 To data.Length - 1
properties.Add(New IndexProperty(i, GetType(Object), New Attribute() {}))
Next
Return New PropertyDescriptorCollection(properties.ToArray())
End Function
Default Public Property Item(ByVal i As Integer) As Object
Get
Return data(i).GetType().GetProperty(PropertyName).GetValue(data(i))
End Get
Set(ByVal value As Object)
data(i).GetType().GetProperty(PropertyName).SetValue(data(i), Convert.ChangeType(value, Type))
End Set
End Property
End Class
Public Class IndexProperty
Inherits PropertyDescriptor
Private index As Integer
Private type As Type
Public Sub New(ByVal index As Integer, ByVal type As Type, ByVal attributes As Attribute())
MyBase.New(index.ToString(), attributes)
Me.index = index
Me.type = type
End Sub
Public Overrides ReadOnly Property ComponentType As Type
Get
Return GetType(RotatedItem)
End Get
End Property
Public Overrides ReadOnly Property IsReadOnly As Boolean
Get
Return False
End Get
End Property
Public Overrides ReadOnly Property PropertyType As Type
Get
Return type
End Get
End Property
Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
Return False
End Function
Public Overrides Function GetValue(ByVal component As Object) As Object
Return (CType(component, RotatedItem))(index)
End Function
Public Overrides Sub ResetValue(ByVal component As Object)
End Sub
Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object)
CType(component, RotatedItem)(index) = value
End Sub
Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
Return True
End Function
End Class
Public Class PropertyNameProperty
Inherits PropertyDescriptor
Public Sub New(ByVal attributes As Attribute())
MyBase.New(NameOf(RotatedItem.PropertyName), attributes)
End Sub
Public Overrides ReadOnly Property ComponentType As Type
Get
Return GetType(RotatedItem)
End Get
End Property
Public Overrides ReadOnly Property IsReadOnly As Boolean
Get
Return True
End Get
End Property
Public Overrides ReadOnly Property PropertyType As Type
Get
Return GetType(String)
End Get
End Property
Public Overrides Function CanResetValue(ByVal component As Object) As Boolean
Return False
End Function
Public Overrides Function GetValue(ByVal component As Object)
Return (CType(component, RotatedItem)).PropertyName
End Function
Public Overrides Sub ResetValue(ByVal component As Object)
End Sub
Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object)
End Sub
Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean
Return True
End Function
End Class
员工班级
这是在旋转数据源的示例用法中使用的 Employee 类
Public Class Employee
Public Property Id As Integer
Public Property Name As String
Public Property City As String
End Class
示例 以下示例展示了如何在 DataGridView 中显示旋转列表(转置列表):
Imports System.ComponentModel
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Data
Dim list As New List(Of Employee) From
{
New Employee With {.Id = 1, .Name = "John", .City = "New York"},
New Employee With {.Id = 2, .Name = "Steve", .City = "London"},
New Employee With {.Id = 3, .Name = "Lucas", .City = "Paris"}
}
'Set Data Source of the DataGridView
DGV.DataSource = New RotatedListDataSource(Of Employee)(list)
'Hide Column Headers
DGV.ColumnHeadersVisible = False
'Set Row Headers Autosize
DGV.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders
'Show PropertyName on RowHeader
AddHandler DGV.RowPrePaint,
Sub(o, a)
Dim value = CType(DGV.Rows(a.RowIndex).DataBoundItem, RotatedItem).PropertyName
If a.RowIndex > -1 And $"{DGV.Rows(a.RowIndex).HeaderCell.Value}" <> value Then
DGV.Rows(a.RowIndex).HeaderCell.Value = value
End If
End Sub
End Sub
End Class