How to assign class property as display data membe

2019-08-12 15:53发布

问题:

I am trying to display my data in datagridview. I created a class with different property and used its list as the datasource. it worked fine. but I got confused how to do that in case we have nested class.

My Classes are as follows:

class Category
   property UIN as integer
   property Name as string
end class

class item
   property uin as integer
   property name as string
   property mycategory as category
end class

my data list as follows:

dim myDataList as list(of Item) = new List(of Item)
myDataList.Add(new Item(1,"item1",new category(1,"cat1")))
myDataList.Add(new Item(2,"item2",new category(1,"cat1")))
myDataList.Add(new Item(3,"item3",new category(1,"cat1")))
myDataList.Add(new Item(4,"item4",new category(2,"cat2")))
myDataList.Add(new Item(5,"item5",new category(2,"cat2")))
myDataList.Add(new Item(6,"item6",new category(2,"cat2")))

Now I binded the datagridview control like:

DGVMain.AutoGenerateColumns = False
DGVMain.ColumnCount = 3
DGVMain.Columns(0).DataPropertyName = "UIN"
DGVMain.Columns(0).HeaderText = "ID"
DGVMain.Columns(1).DataPropertyName = "Name"
DGVMain.Columns(1).HeaderText = "Name"
DGVMain.Columns(2).DataPropertyName = "" **'here i want my category name**
DGVMain.Columns(2).HeaderText = "category"

DGVMain.datasource = myDataList
DGVMain.refresh()

I have tried using mycategory.name but it didn't worked. What can be done to get expected result? Is there any better idea other than this to accomplish the same task?

Edited My question as per comment:

I have checked the link given by u. It was nice n very usefull. Since the code was in c# i tried to convert it in vb. Everything went good but failed at a point of case sensitive and next one is that i had my nested class name itemcategory and my property name was category. there it arouse the problem. it didn't searched for category but it searched for itemcategory. so confused on it. My Code as follows:

Private Sub DGVMain_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DGVMain.CellFormatting
    Dim DGVMain As DataGridView = CType(sender, DataGridView)
    e.Value = EvaluateValue(DGVMain.Rows(e.RowIndex).DataBoundItem, DGVMain.Columns(e.ColumnIndex).DataPropertyName)
End Sub

Private Function EvaluateValue(ByRef myObj As Object, ByRef myProp As String) As String
    Dim Ret As String = ""
    Dim Props As System.Reflection.PropertyInfo()
    Dim PropA As System.Reflection.PropertyInfo
    Dim ObjA As Object

    If myProp.Contains(".") Then

        myProp = myProp.Substring(0, myProp.IndexOf("."))
        Props = myObj.GetType().GetProperties()

        For Each PropA In Props

            ObjA = PropA.GetValue(myObj, New Object() {})
            If ObjA.GetType().Name = myProp Then

                Ret = EvaluateValue(ObjA, myProp.Substring(myProp.IndexOf(".") + 1))
                Exit For

            End If

        Next

    Else

        PropA = myObj.GetType().GetProperty(myProp)
        Ret = PropA.GetValue(myObj, New Object() {}).ToString()

    End If

    Return Ret
End Function

回答1:

I'd just add a property to item called CategoryName that returns Category.Name and use that.

The Category is part of the Item, but that doesn't mean that you always have to give access to the whole Category to outside classes, just give access to the bits that they need access to at that time as to maximize encapsulation and minimize interdependencies.

Edit: In response to your comment

If you don't want to create the properties as mentioned in my answer above I don't think there is any real solution but you can use the 'CellFormatting' event to sort of get it to work where you set the DataPropertyName to a special identifier and then in the CellFormatting event handler you look up the real value to display. You can find an example of that here, look for tkrasinger's post (or AlexHinton's if you want to use reflection).



回答2:

Public Class Category
    Dim uni As Integer
    Dim name As String
    Public Sub New(ByVal i As Integer, ByVal n As String)
        Me.UIN = i
        Me.name = n
    End Sub
    Public Sub New()

    End Sub
    Property UIN() As Integer
        Get
            Return uni


        End Get
        Set(ByVal value As Integer)
            uni = value

        End Set
    End Property
    Property Names() As String
        Get
            Return Me.name

        End Get
        Set(ByVal value As String)
            Me.name = value
        End Set
    End Property
    **Public Overrides Function ToString() As String
        Return name.ToString()
    End Function**
End Class

Public Class item
    Dim uni As Integer
    Dim name As String
    Dim category As New Category()

    Property UIN() As Integer
        Get
            Return uni


        End Get
        Set(ByVal value As Integer)
            uni = value

        End Set
    End Property
    Property Names() As String
        Get
            Return Me.name

        End Get
        Set(ByVal value As String)
            Me.name = value
        End Set
    End Property
    Property mycategory() As Category
        Get
            Return Me.category
        End Get
        Set(ByVal value As Category)
            Me.category = value
        End Set
    End Property
    Public Sub New(ByVal i As Integer, ByVal nm As String, ByVal ct As Category)
        Me.UIN = i
        Me.Names = nm
        Me.mycategory = ct
    End Sub
End Class

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim myDataList As List(Of item) = New List(Of item)
    myDataList.Add(New item(1, "item1", New Category(1, "cat1")))
    myDataList.Add(New item(2, "item2", New Category(1, "cat1")))
    myDataList.Add(New item(3, "item3", New Category(1, "cat1")))
    myDataList.Add(New item(4, "item4", New Category(2, "cat2")))
    myDataList.Add(New item(5, "item5", New Category(2, "cat2")))
    myDataList.Add(New item(6, "item6", New Category(2, "cat2")))


    DGVMain.AutoGenerateColumns = False
    DGVMain.ColumnCount = 3
    DGVMain.Columns(0).DataPropertyName = "UIN"
    DGVMain.Columns(0).HeaderText = "ID"
    DGVMain.Columns(1).DataPropertyName = "Names"
    DGVMain.Columns(1).HeaderText = "Name"
    **DGVMain.Columns(2).DataPropertyName = "mycategory"**
    DGVMain.Columns(2).HeaderText = "Category"

    DGVMain.datasource = myDataList
    DGVMain.refresh()
End Sub