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
相关产品推荐
相关产品推荐

