ASP.NET(VB.NET)菜单权限配置页面开发求助:ListBox联动+暂存
主菜单与子菜单权限配置页面逻辑完善(ASP.NET+VB.NET)
需求概述
- 主菜单权限切换(锁定/开启)时,下属所有子菜单权限同步变更
- 权限状态通过两组ListBox展示:
- 主菜单:
Dikunci(锁定列表)、Dibuka(开启列表) - 子菜单:
Dikunci1(锁定列表)、Dibuka1(开启列表)
- 主菜单:
- 手动调整权限后变更暂存,点击Simpan按钮才持久化生效
- 点击Batal按钮放弃所有未保存的权限调整
现有ASPX页面代码
<div class="form-group" id="Modul" runat="server" visible="false"> <div class="form-group" id="snippet1Content" runat="server" visible="true"> <label class="col-md-3 control-label"></label> <div class="col-md-4"> <label>Dikunci</label> <asp:ListBox ID="Dikunci" runat="server" Width="300px" Height="170px" AutoPostBack="True" SelectionMode="Multiple" onchange="updateSubMenuList()"></asp:ListBox> <div> <label>Dikunci</label> <asp:ListBox ID="Dikunci1" runat="server" Width="300px" Height="170px" AutoPostBack="True" SelectionMode="Multiple" onchange="updateSubMenuList()"></asp:ListBox> </div> </div> <div class="col-md-4"> <label>Dibuka</label> <asp:ListBox ID="Dibuka" runat="server" Width="300px" Height="170px" AutoPostBack="True" SelectionMode="Multiple" onchange="updateSubMenuList()"></asp:ListBox> <div> <label>Dibuka</label> <asp:ListBox ID="Dibuka1" runat="server" Width="300px" Height="170px" AutoPostBack="True" SelectionMode="Multiple" onchange="updateSubMenuList()"></asp:ListBox> </div> </div> </div> <div class="col-md-offset-3 col-md-9" id="panel_btnAll" runat="server" visible="true"> <asp:Button runat="server" ID="btnSimpan" Text="Simpan" class="fa fa-check" CssClass="btn green" /> <asp:Button runat="server" ID="btnBatal" Text="Batal" CssClass="btn red" /> </div> </div>
后端VB.NET逻辑完善
1. 菜单实体类
Public Class MenuItem Public Property MenuId As Integer Public Property MenuName As String Public Property ParentId As Integer? ' 主菜单ParentId为Nothing,子菜单对应主MenuId Public Property IsEnabled As Boolean ' True=开启,False=锁定 End Class
2. 页面加载与数据绑定
Private originalMenuList As List(Of MenuItem) ' 存储原始权限状态,用于取消功能 Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load If Not IsPostBack Then ' 从数据库加载所有菜单数据(替换为实际数据访问代码) originalMenuList = LoadMenuPermissionsFromDB() BindMenuListBoxes(originalMenuList) Modul.Visible = True ' 显示权限配置模块 End If End Sub ' 绑定菜单到对应的ListBox Private Sub BindMenuListBoxes(menuList As List(Of MenuItem)) ' 绑定主菜单 Dim mainMenus = menuList.Where(Function(m) m.ParentId Is Nothing).ToList() Dikunci.Items.Clear() Dibuka.Items.Clear() For Each menu In mainMenus Dim item As New ListItem(menu.MenuName, menu.MenuId.ToString()) If menu.IsEnabled Then Dibuka.Items.Add(item) Else Dikunci.Items.Add(item) End If Next ' 绑定子菜单 Dim subMenus = menuList.Where(Function(m) m.ParentId IsNot Nothing).ToList() Dikunci1.Items.Clear() Dibuka1.Items.Clear() For Each menu In subMenus Dim item As New ListItem(menu.MenuName, menu.MenuId.ToString()) If menu.IsEnabled Then Dibuka1.Items.Add(item) Else Dikunci1.Items.Add(item) End If Next End Sub ' 模拟从数据库加载权限数据 Private Function LoadMenuPermissionsFromDB() As List(Of MenuItem) Return New List(Of MenuItem) From { New MenuItem With {.MenuId = 1, .MenuName = "用户管理", .ParentId = Nothing, .IsEnabled = True}, New MenuItem With {.MenuId = 2, .MenuName = "角色管理", .ParentId = Nothing, .IsEnabled = False}, New MenuItem With {.MenuId = 3, .MenuName = "用户列表", .ParentId = 1, .IsEnabled = True}, New MenuItem With {.MenuId = 4, .MenuName = "用户新增", .ParentId = 1, .IsEnabled = True}, New MenuItem With {.MenuId = 5, .MenuName = "角色列表", .ParentId = 2, .IsEnabled = False} } End Function
3. 主菜单变更同步子菜单
' 主菜单锁定列表变更事件 Protected Sub Dikunci_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Dikunci.SelectedIndexChanged SyncSubMenusByMainMenu(Dikunci, False) ' 移动到锁定列表,子菜单同步锁定 End Sub ' 主菜单开启列表变更事件 Protected Sub Dibuka_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Dibuka.SelectedIndexChanged SyncSubMenusByMainMenu(Dibuka, True) ' 移动到开启列表,子菜单同步开启 End Sub ' 同步主菜单对应的所有子菜单权限 Private Sub SyncSubMenusByMainMenu(sourceListBox As ListBox, isEnabled As Boolean) For Each selectedItem In sourceListBox.SelectedItems.Cast(Of ListItem).ToList() Dim mainMenuId = Integer.Parse(selectedItem.Value) Dim targetSubList = If(isEnabled, Dibuka1, Dikunci1) Dim sourceSubList = If(isEnabled, Dikunci1, Dibuka1) ' 遍历子菜单列表,匹配当前主菜单的子项并移动 For Each subItem In sourceSubList.Items.Cast(Of ListItem).ToList() Dim subMenu = originalMenuList.FirstOrDefault(Function(m) m.MenuId = Integer.Parse(subItem.Value)) If subMenu IsNot Nothing AndAlso subMenu.ParentId = mainMenuId Then sourceSubList.Items.Remove(subItem) targetSubList.Items.Add(subItem) End If Next Next sourceListBox.ClearSelection() End Sub
4. 保存与取消按钮逻辑
' 保存按钮事件 Protected Sub btnSimpan_Click(sender As Object, e As EventArgs) Handles btnSimpan.Click Dim updatedMenuList = New List(Of MenuItem)() ' 收集主菜单权限状态 For Each item In Dikunci.Items.Cast(Of ListItem)() updatedMenuList.Add(New MenuItem With { .MenuId = Integer.Parse(item.Value), .MenuName = item.Text, .ParentId = Nothing, .IsEnabled = False }) Next For Each item In Dibuka.Items.Cast(Of ListItem)() updatedMenuList.Add(New MenuItem With { .MenuId = Integer.Parse(item.Value), .MenuName = item.Text, .ParentId = Nothing, .IsEnabled = True }) Next ' 收集子菜单权限状态 For Each item In Dikunci1.Items.Cast(Of ListItem)() Dim subMenu = originalMenuList.FirstOrDefault(Function(m) m.MenuId = Integer.Parse(item.Value)) If subMenu IsNot Nothing Then updatedMenuList.Add(New MenuItem With { .MenuId = subMenu.MenuId, .MenuName = item.Text, .ParentId = subMenu.ParentId, .IsEnabled = False }) End If Next For Each item In Dibuka1.Items.Cast(Of ListItem)() Dim subMenu = originalMenuList.FirstOrDefault(Function(m) m.MenuId = Integer.Parse(item.Value)) If subMenu IsNot Nothing Then updatedMenuList.Add(New MenuItem With { .MenuId = subMenu.MenuId, .MenuName = item.Text, .ParentId = subMenu.ParentId, .IsEnabled = True }) End If Next ' 保存到数据库(替换为实际数据访问代码) SaveMenuPermissionsToDB(updatedMenuList) originalMenuList = updatedMenuList ClientScript.RegisterStartupScript(Me.GetType(), "alert", "alert('权限配置已保存');", True) End Sub ' 取消按钮事件 Protected Sub btnBatal_Click(sender As Object, e As EventArgs) Handles btnBatal.Click ' 重置为原始权限状态 BindMenuListBoxes(originalMenuList) ClientScript.RegisterStartupScript(Me.GetType(), "alert", "alert('已取消所有未保存变更');", True) End Sub ' 模拟保存到数据库 Private Sub SaveMenuPermissionsToDB(menuList As List(Of MenuItem)) ' 此处编写实际的数据库更新逻辑 End Sub
前端JS辅助逻辑
在ASPX页面的<script>标签中添加以下代码,优化用户交互体验:
function updateSubMenuList() { // 可选:前端预同步子菜单,减少回发等待感 // 示例逻辑可根据实际需求扩展,后端已处理核心同步逻辑 }
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

