You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ListItem仅支持双值绑定,如何跨方法获取主菜单关联数据?

解决方案:在ListBox中存储并获取主菜单额外数据

针对你遇到的ListItem自定义属性无法跨方法获取的问题,核心原因是ASP.NET中ListItem的Attributes不会自动持久化到ViewState,页面回发后属性值会丢失。以下是几种可行的解决办法:


方法一:利用ListItem的Tag属性存储自定义对象

通过封装主菜单信息到类实例,存入ListItem.Tag,后续直接从Tag中读取强类型数据,是最简洁可靠的方案。

1. 定义主菜单信息类

Public Class MenuInfo
    Public Property ObjectId As String
    Public Property ObjectDesc As String
    ' 可按需扩展其他属性
End Class

2. 绑定数据时存储到Tag

修改你的BindDataToListBox方法,将主菜单信息存入每个ListItem的Tag:

Public Sub BindDataToListBox(ByVal menuData As DataTable, ByVal dikunciListBox As ListBox,
                          ByVal dibukaListBox As ListBox, ByVal dikunci1ListBox As ListBox, ByVal dibuka1ListBox As ListBox)

    Dim lastMainMenu As String = ""

    For Each row As DataRow In menuData.Rows
        Dim objectId As String = row("OBJECTID").ToString()
        Dim objectDesc As String = row("OBJECTDESC").ToString()
        Dim objectType As String = row("OBJECTTYPE").ToString()
        Dim iAllowValue As String = row("IALLOW").ToString()

        If String.IsNullOrEmpty(iAllowValue) OrElse iAllowValue = "0" Then
            Dim menuInfo As New MenuInfo With {.ObjectId = objectId, .ObjectDesc = objectDesc}
            Dim item As New ListItem(objectDesc, objectId)
            item.Tag = menuInfo
            dikunciListBox.Items.Add(item)
        ElseIf iAllowValue = "1" Then
            Dim menuInfo As New MenuInfo With {.ObjectId = objectId, .ObjectDesc = objectDesc}
            Dim dibukaItem As New ListItem(objectDesc, objectId)
            dibukaItem.Tag = menuInfo
            dibukaListBox.Items.Add(dibukaItem)

            Dim submenus As DataTable = Nothing
            submenus = objClass.GetSubMenuDataPR(ddlIdStaff.SelectedItem.Value, objectId)

            If submenus IsNot Nothing AndAlso submenus.Rows.Count > 0 Then

                Dim hasIAAllowZero As String = If(submenus.AsEnumerable().Any(Function(subRow) Not IsDBNull(subRow("IALLOW")) AndAlso Convert.ToDecimal(subRow("IALLOW")) = 0), "True", "False")
                Dim hasIAAllowOne As String = If(submenus.AsEnumerable().Any(Function(subRow) Not IsDBNull(subRow("IALLOW")) AndAlso Convert.ToDecimal(subRow("IALLOW")) = 1), "True", "False")

                If hasIAAllowZero = "True" OrElse hasIAAllowZero Is Nothing Then
                    DisplayMenuLabelClose(objectDesc, objectId)
                End If

                If hasIAAllowOne = "True" Then
                    DisplayMenuLabel(objectDesc, objectId)
                End If

                For Each subRow As DataRow In submenus.Rows
                    Dim subObjectId As String = subRow("OBJECTID").ToString()
                    Dim subObjectDesc As String = subRow("OBJECTDESC").ToString()
                    Dim subIAAllowValue As String = subRow("IALLOW").ToString()

                    If String.IsNullOrEmpty(subIAAllowValue) OrElse subIAAllowValue = "0" Then
                        Dim menuInfo As New MenuInfo With {.ObjectId = objectId, .ObjectDesc = objectDesc}
                        Dim dikunci1Item As New ListItem(subObjectDesc, subObjectId)
                        dikunci1Item.Tag = menuInfo
                        dikunci1ListBox.Items.Add(dikunci1Item)
                    ElseIf subIAAllowValue = "1" Then
                        Dim menuInfo As New MenuInfo With {.ObjectId = objectId, .ObjectDesc = objectDesc}
                        Dim dibuka1Item As New ListItem(subObjectDesc, subObjectId)
                        dibuka1Item.Tag = menuInfo
                        dibuka1ListBox.Items.Add(dibuka1Item)
                    End If
                Next
            End If
        End If
    Next
End Sub

3. 在其他方法中获取数据

比如在ListBox选中事件中读取:

Private Sub dibukaListBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles dibukaListBox.SelectedIndexChanged
    If dibukaListBox.SelectedItem IsNot Nothing Then
        Dim menuInfo = DirectCast(dibukaListBox.SelectedItem.Tag, MenuInfo)
        Dim mainMenuId = menuInfo.ObjectId
        Dim mainMenuDesc = menuInfo.ObjectDesc
        ' 后续业务逻辑处理
    End If
End Sub

方法二:手动将Attributes存入ViewState(适合简单场景)

如果坚持使用Attributes,需要手动把属性值保存到ViewState,页面回发后重新绑定属性:

1. 绑定数据时记录属性到ViewState

在BindDataToListBox方法末尾,将所有ListItem的自定义属性存入ViewState:

' 存储dibukaListBox的属性
ViewState("DibukaListAttributes") = dibukaListBox.Items.Cast(Of ListItem)().ToDictionary(
    Function(item) item.Value,
    Function(item) New With {
        .MainMenuObjectId = item.Attributes("MainMenuObjectId"),
        .MainMenuObjectDesc = item.Attributes("MainMenuObjectDesc")
    }
)

' 同理存储其他ListBox的属性
ViewState("Dikunci1ListAttributes") = dikunci1ListBox.Items.Cast(Of ListItem)().ToDictionary(
    Function(item) item.Value,
    Function(item) New With {
        .MainMenuObjectId = item.Attributes("MainMenuObjectId"),
        .MainMenuObjectDesc = item.Attributes("MainMenuObjectDesc")
    }
)

ViewState("Dibuka1ListAttributes") = dibuka1ListBox.Items.Cast(Of ListItem)().ToDictionary(
    Function(item) item.Value,
    Function(item) New With {
        .MainMenuObjectId = item.Attributes("MainMenuObjectId"),
        .MainMenuObjectDesc = item.Attributes("MainMenuObjectDesc")
    }
)

2. 页面回发后重新绑定属性

在Page_Load事件中,判断回发后重新给ListItem赋值属性:

Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
    If IsPostBack Then
        ' 恢复dibukaListBox的属性
        If ViewState("DibukaListAttributes") IsNot Nothing Then
            Dim attrDict = DirectCast(ViewState("DibukaListAttributes"), Dictionary(Of String, Object))
            For Each item As ListItem In dibukaListBox.Items
                If attrDict.ContainsKey(item.Value) Then
                    Dim attr = attrDict(item.Value)
                    item.Attributes("MainMenuObjectId") = attr.MainMenuObjectId
                    item.Attributes("MainMenuObjectDesc") = attr.MainMenuObjectDesc
                End If
            Next
        End If

        ' 同理恢复dikunci1ListBox和dibuka1ListBox的属性
        If ViewState("Dikunci1ListAttributes") IsNot Nothing Then
            Dim attrDict = DirectCast(ViewState("Dikunci1ListAttributes"), Dictionary(Of String, Object))
            For Each item As ListItem In dikunci1ListBox.Items
                If attrDict.ContainsKey(item.Value) Then
                    Dim attr = attrDict(item.Value)
                    item.Attributes("MainMenuObjectId") = attr.MainMenuObjectId
                    item.Attributes("MainMenuObjectDesc") = attr.MainMenuObjectDesc
                End If
            Next
        End If

        If ViewState("Dibuka1ListAttributes") IsNot Nothing Then
            Dim attrDict = DirectCast(ViewState("Dibuka1ListAttributes"), Dictionary(Of String, Object))
            For Each item As ListItem In dibuka1ListBox.Items
                If attrDict.ContainsKey(item.Value) Then
                    Dim attr = attrDict(item.Value)
                    item.Attributes("MainMenuObjectId") = attr.MainMenuObjectId
                    item.Attributes("MainMenuObjectDesc") = attr.MainMenuObjectDesc
                End If
            Next
        End If
    End If
End Sub

3. 其他方法中获取属性

此时就可以正常读取Attributes了:

If dibukaListBox.SelectedItem IsNot Nothing Then
    Dim mainMenuId = dibukaListBox.SelectedItem.Attributes("MainMenuObjectId")
    Dim mainMenuDesc = dibukaListBox.SelectedItem.Attributes("MainMenuObjectDesc")
End If

方法三:使用自定义ListItem类(进阶)

创建继承自ListItem的自定义类,添加强类型属性并重写ViewState相关方法确保持久化:

1. 自定义ListItem类

Public Class CustomListItem
    Inherits ListItem
    Public Property MainMenuObjectId As String
    Public Property MainMenuObjectDesc As String

    ' 重写SaveViewState保存自定义属性
    Protected Overrides Function SaveViewState() As Object
        Dim baseState = MyBase.SaveViewState()
        ' 保存基类状态+自定义属性
        Return New Object() {baseState, MainMenuObjectId, MainMenuObjectDesc}
    End Function

    ' 重写LoadViewState恢复自定义属性
    Protected Overrides Sub LoadViewState(savedState As Object)
        Dim stateArray = DirectCast(savedState, Object())
        MyBase.LoadViewState(stateArray(0))
        MainMenuObjectId = DirectCast(stateArray(1), String)
        MainMenuObjectDesc = DirectCast(stateArray(2), String)
    End Sub
End Class

2. 绑定数据时使用自定义类

Dim dibukaItem As New CustomListItem(objectDesc, objectId)
dibukaItem.MainMenuObjectId = objectId
dibukaItem.MainMenuObjectDesc = objectDesc
dibukaListBox.Items.Add(dibukaItem)

3. 其他方法中获取数据

直接强类型转换读取:

If dibukaListBox.SelectedItem IsNot Nothing Then
    Dim customItem = DirectCast(dibukaListBox.SelectedItem, CustomListItem)
    Dim mainMenuId = customItem.MainMenuObjectId
    Dim mainMenuDesc = customItem.MainMenuObjectDesc
End If

内容的提问来源于stack exchange,提问作者Anonymous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:57:23