使用 vb.net 从列表和数据表转置可编辑 DataGridView

问题描述 投票:0回答:1

我正在尝试使用 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

我的代码的结果

screenshot result code 25102024

想要的结果

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.net winforms datatable datagridview ienumerable
1个回答
0
投票

这是我的原始帖子的 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
© www.soinside.com 2019 - 2024. All rights reserved.