Ext.Net 1.2.0_演示为权限控制动态创建按钮的一个解决方案-02_2
定义系统按钮 XML 文件
<?xml version="1.0" encoding="utf-8"?>
<buttons name="SysButton">
<button id="1" text="待提交" parentid="-1" buttontype="WaitCommit" buttonaction="Status" >
<button id="2" text="添加" parentid="1" buttontype="GroupCommand" buttonaction="Add" />
<button id="3" text="提交" parentid="1" buttontype="Command" buttonaction="Commit" />
<button id="4" text="删除" parentid="1" buttontype="Command" buttonaction="Delete" />
<button id="5" text="修改" parentid="1" buttontype="Command" buttonaction="Edit" />
</button>
<button id="6" text="待审核" parentid="-1" buttontype="WaitCheck" buttonaction="Status">
<button id="7" text="审核" parentid="6" buttontype="Command" buttonaction="Check" />
<button id="8" text="取消" parentid="6" buttontype="Command" buttonaction="Cancel" />
</button>
<button id="9" text="已审核" parentid="-1" buttontype="Checked" buttonaction="Status">
</button>
</buttons>
定义系统按钮对应的 ButtonType 和 ButtonAction 枚举
using System;
namespace ExtNetDynamicButton
{/// <summary>
/// 按钮类型
/// </summary>
public enum ButtonType{/// <summary>
/// 待提交
/// </summary>
WaitCommit = 0,/// <summary>
/// 待审核
/// </summary>
WaitCheck = 1,/// <summary>
/// 已审核
/// </summary>
Checked = 2,/// <summary>
/// 状态
/// </summary>
Status,/// <summary>
/// Grid 组按钮
/// </summary>
GroupCommand,/// <summary>
/// Grid 行按钮
/// </summary>
Command}public enum ButtonAction{/// <summary>
/// 创建
/// </summary>
Add,/// <summary>
/// 提交
/// </summary>
Commit,/// <summary>
/// 删除
/// </summary>
Delete,/// <summary>
/// 编辑
/// </summary>
Edit,/// <summary>
/// 审核
/// </summary>
Check,/// <summary>
/// 取消
/// </summary>
Cancel,/// <summary>
/// 状态切换
/// </summary>
Status}}
说明:
- 系统按钮当然可以已数据库表的形式;
- 简单指定每个 XML 节点的属性 id、text、parentid、buttontype、buttonaction 分别表示按钮的编号、名称、父编号、按钮类型、按钮动作。如,buttontype=WaitCommit 表示该按钮的状态为“待提交”;buttontype=GroupCommand 表示该按钮为 grid 行组按钮;buttontype=Command 表示该按钮为 grid 的行按钮等。
定义系统按钮类
该类用于读取系统按钮 XML 文件。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
using System.Globalization;
namespace ExtNetDynamicButton
{
[Serializable]
public class MyButton
{
public MyButton()
{ }
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="name"></param>
/// <param name="parentId"></param>
/// <param name="buttonType"></param>
/// <param name="buttonAction"></param>
public MyButton(int id, string name, int parentId, ButtonType buttonType, ButtonAction buttonAction)
{
this.Id = id;
this.Name = name;
this.ParentId = parentId;
this.ButtonType = buttonType;
this.ButtonAction = buttonAction;
}
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public ButtonType ButtonType { get; set; }
public ButtonAction ButtonAction { get; set; }
public static List<MyButton> ButtonList
{
get { return GetButtons(); }
}
private static List<MyButton> GetButtons()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(HttpContext.Current.Server.MapPath("MyButtons.xml"));
List<MyButton> buttonList = new List<MyButton>();
foreach (XmlNode node in xmlDoc.SelectSingleNode("buttons").ChildNodes)
{
MyButton button = new MyButton();
foreach (XmlAttribute nodeAttrib in node.Attributes)
{
switch (nodeAttrib.Name)
{
case "id": button.Id = Convert.ToInt16(nodeAttrib.Value); break;
case "text": button.Name = nodeAttrib.Value; break;
case "parentid": button.ParentId = Convert.ToInt16(nodeAttrib.Value); break;
case "buttontype": button.ButtonType = (ButtonType)Enum.Parse(typeof(ButtonType), nodeAttrib.Value, true); break;
case "buttonaction": button.ButtonAction = (ButtonAction)Enum.Parse(typeof(ButtonAction), nodeAttrib.Value, true); break;
}
}
buttonList.Add(button);
GetButtons(node.ChildNodes, buttonList);
}
return buttonList;
}
private static void GetButtons(XmlNodeList nodes, List<MyButton> buttonList)
{
foreach (XmlNode node in nodes)
{
MyButton button = new MyButton();
foreach (XmlAttribute nodeAttrib in node.Attributes)
{
switch (nodeAttrib.Name)
{
case "id": button.Id = Convert.ToInt16(nodeAttrib.Value); break;
case "text": button.Name = nodeAttrib.Value; break;
case "parentid": button.ParentId = Convert.ToInt16(nodeAttrib.Value); break;
case "buttontype": button.ButtonType = (ButtonType)Enum.Parse(typeof(ButtonType), nodeAttrib.Value, true); break;
case "buttonaction": button.ButtonAction = (ButtonAction)Enum.Parse(typeof(ButtonAction), nodeAttrib.Value, true); break;
}
}
buttonList.Add(button);
GetButtons(node.ChildNodes, buttonList);
}
}
}
}
定义授权用户按钮 XML 文件
假设有三个用户 u1、u2 和 admin,授权后如下所示:
<?xml version="1.0" encoding="utf-8"?>
<users>
<u1>
<button id="1" text="待提交" parentid="-1" buttontype="WaitCommit" buttonaction="Status" >
<button id="2" text="添加" parentid="1" buttontype="GroupCommand" buttonaction="Add" />
<button id="3" text="提交" parentid="1" buttontype="Command" buttonaction="Commit" />
<button id="5" text="修改" parentid="1" buttontype="Command" buttonaction="Edit" />
</button>
<button id="6" text="待审核" parentid="-1" buttontype="WaitCheck" buttonaction="Status">
<button id="8" text="取消" parentid="6" buttontype="Command" buttonaction="Cancel" />
</button>
</u1>
<u2>
<button id="6" text="待审核" parentid="-1" buttontype="WaitCheck" buttonaction="Status">
<button id="7" text="审核" parentid="6" buttontype="Command" buttonaction="Check" />
<button id="8" text="取消" parentid="6" buttontype="Command" buttonaction="Cancel" />
</button>
<button id="9" text="已审核" parentid="-1" buttontype="Checked" buttonaction="Status">
</button>
</u2>
<admin>
<button id="1" text="待提交" parentid="-1" buttontype="WaitCommit" buttonaction="Status" >
<button id="2" text="添加" parentid="1" buttontype="GroupCommand" buttonaction="Add" />
<button id="3" text="提交" parentid="1" buttontype="Command" buttonaction="Commit" />
<button id="4" text="删除" parentid="1" buttontype="Command" buttonaction="Delete" />
<button id="5" text="修改" parentid="1" buttontype="Command" buttonaction="Edit" />
</button>
<button id="6" text="待审核" parentid="-1" buttontype="WaitCheck" buttonaction="Status">
<button id="7" text="审核" parentid="6" buttontype="Command" buttonaction="Check" />
<button id="8" text="取消" parentid="6" buttontype="Command" buttonaction="Cancel" />
</button>
<button id="9" text="已审核" parentid="-1" buttontype="Checked" buttonaction="Status">
</button>
</admin>
</users>
说明:
- 用户授权的按钮当然可以已数据库表的形式。
定义授权用户按钮类
该类用于读取用户按钮 XML 文件。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
namespace ExtNetDynamicButton
{
public class MyUser
{
public string Name { get; set; }
public List<MyButton> Buttons { get; set; }
public static List<MyUser> UsersList
{
get { return GetUsers(); }
}
private static List<MyUser> GetUsers()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(HttpContext.Current.Server.MapPath("MyUsers.xml"));
List<MyUser> userList = new List<MyUser>();
XmlNode userNode = xmlDoc.SelectSingleNode("users");
foreach (XmlNode node in userNode.ChildNodes)
{
MyUser user = new MyUser();
user.Name = node.Name;
user.Buttons = GetButtons(node.ChildNodes);
userList.Add(user);
}
return userList;
}
private static List<MyButton> GetButtons(XmlNodeList nodes)
{
List<MyButton> buttonList = new List<MyButton>();
foreach (XmlNode node in nodes)
{
MyButton button = new MyButton();
foreach (XmlAttribute nodeAttrib in node.Attributes)
{
switch (nodeAttrib.Name)
{
case "id": button.Id = Convert.ToInt16(nodeAttrib.Value); break;
case "text": button.Name = nodeAttrib.Value; break;
case "parentid": button.ParentId = Convert.ToInt16(nodeAttrib.Value); break;
case "buttontype": button.ButtonType = (ButtonType)Enum.Parse(typeof(ButtonType), nodeAttrib.Value, true); break;
case "buttonaction": button.ButtonAction = (ButtonAction)Enum.Parse(typeof(ButtonAction), nodeAttrib.Value, true); break;
}
}
buttonList.Add(button);
GetButtons(node.ChildNodes, buttonList);
}
return buttonList;
}
private static void GetButtons(XmlNodeList nodes, List<MyButton> buttonList)
{
foreach (XmlNode node in nodes)
{
MyButton button = new MyButton();
foreach (XmlAttribute nodeAttrib in node.Attributes)
{
switch (nodeAttrib.Name)
{
case "id": button.Id = Convert.ToInt16(nodeAttrib.Value); break;
case "text": button.Name = nodeAttrib.Value; break;
case "parentid": button.ParentId = Convert.ToInt16(nodeAttrib.Value); break;
case "buttontype": button.ButtonType = (ButtonType)Enum.Parse(typeof(ButtonType), nodeAttrib.Value, true); break;
case "buttonaction": button.ButtonAction = (ButtonAction)Enum.Parse(typeof(ButtonAction), nodeAttrib.Value, true); break;
}
}
buttonList.Add(button);
GetButtons(node.ChildNodes, buttonList);
}
}
}
}
定义数据 XML 文件
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<plant>
<id>1</id>
<common>Bloodroot</common>
<botanical>Sanguinaria canadensis</botanical>
<zone>4</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>2.44</price>
<availability>03/15/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>2</id>
<common>Columbine</common>
<botanical>Aquilegia canadensis</botanical>
<zone>3</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>9.37</price>
<availability>03/06/2006</availability>
<indoor>false</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>3</id>
<common>Marsh Marigold</common>
<botanical>Caltha palustris</botanical>
<zone>4</zone>
<colorCode>F5F5F5</colorCode>
<light>Mostly Sunny</light>
<price>6.81</price>
<availability>05/17/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>4</id>
<common>Cowslip</common>
<botanical>Caltha palustris</botanical>
<zone>4</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>9.90</price>
<availability>03/06/2006</availability>
<indoor>false</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>5</id>
<common>Dutchman's-Breeches</common>
<botanical>Dicentra cucullaria</botanical>
<zone>3</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>6.44</price>
<availability>01/20/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>6</id>
<common>Ginger, Wild</common>
<botanical>Asarum canadense</botanical>
<zone>3</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>9.03</price>
<availability>04/18/2006</availability>
<indoor>false</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>7</id>
<common>Hepatica</common>
<botanical>Hepatica americana</botanical>
<zone>4</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>4.45</price>
<availability>01/26/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>8</id>
<common>Liverleaf</common>
<botanical>Hepatica americana</botanical>
<zone>4</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>3.99</price>
<availability>01/02/2006</availability>
<indoor>false</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>9</id>
<common>Jack-In-The-Pulpit</common>
<botanical>Arisaema triphyllum</botanical>
<zone>4</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>3.23</price>
<availability>02/01/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>10</id>
<common>Mayapple</common>
<botanical>Podophyllum peltatum</botanical>
<zone>3</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>2.98</price>
<availability>06/05/2006</availability>
<indoor>false</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>11</id>
<common>Phlox, Woodland</common>
<botanical>Phlox divaricata</botanical>
<zone>3</zone>
<colorCode>EEEEEE</colorCode>
<light>Sun or Shade</light>
<price>2.80</price>
<availability>01/22/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>12</id>
<common>Phlox, Blue</common>
<botanical>Phlox divaricata</botanical>
<zone>3</zone>
<colorCode>EEEEEE</colorCode>
<light>Sun or Shade</light>
<price>5.59</price>
<availability>02/16/2006</availability>
<indoor>false</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>13</id>
<common>Spring-Beauty</common>
<botanical>Claytonia Virginica</botanical>
<zone>7</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>6.59</price>
<availability>02/01/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>14</id>
<common>Trillium</common>
<botanical>Trillium grandiflorum</botanical>
<zone>5</zone>
<colorCode>EEEEEE</colorCode>
<light>Sun or Shade</light>
<price>3.90</price>
<availability>04/29/2006</availability>
<indoor>false</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>15</id>
<common>Wake Robin</common>
<botanical>Trillium grandiflorum</botanical>
<zone>5</zone>
<colorCode>EEEEEE</colorCode>
<light>Sun or Shade</light>
<price>3.20</price>
<availability>02/21/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>16</id>
<common>Violet, Dog-Tooth</common>
<botanical>Erythronium americanum</botanical>
<zone>4</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>9.04</price>
<availability>02/01/2006</availability>
<indoor>false</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>17</id>
<common>Trout Lily</common>
<botanical>Erythronium americanum</botanical>
<zone>4</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>6.94</price>
<availability>03/24/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>18</id>
<common>Adder's-Tongue</common>
<botanical>Erythronium americanum</botanical>
<zone>4</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>9.58</price>
<availability>04/13/2006</availability>
<indoor>false</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>19</id>
<common>Anemone</common>
<botanical>Anemone blanda</botanical>
<zone>6</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>8.86</price>
<availability>12/26/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>20</id>
<common>Grecian Windflower</common>
<botanical>Anemone blanda</botanical>
<zone>6</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>9.16</price>
<availability>07/10/2006</availability>
<indoor>false</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>21</id>
<common>Bee Balm</common>
<botanical>Monarda didyma</botanical>
<zone>4</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>4.59</price>
<availability>05/03/2006</availability>
<indoor>true</indoor>
<status>WaitCommit</status>
</plant>
<plant>
<id>22</id>
<common>Bergamot</common>
<botanical>Monarda didyma</botanical>
<zone>4</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>7.16</price>
<availability>04/27/2006</availability>
<indoor>false</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>23</id>
<common>Black-Eyed Susan</common>
<botanical>Rudbeckia hirta</botanical>
<zone>Annual</zone>
<colorCode>FFFFFF</colorCode>
<light>Sunny</light>
<price>9.80</price>
<availability>06/18/2006</availability>
<indoor>true</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>24</id>
<common>Buttercup</common>
<botanical>Ranunculus</botanical>
<zone>4</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>2.57</price>
<availability>06/10/2006</availability>
<indoor>false</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>25</id>
<common>Crowfoot</common>
<botanical>Ranunculus</botanical>
<zone>4</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>9.34</price>
<availability>04/03/2006</availability>
<indoor>true</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>26</id>
<common>Butterfly Weed</common>
<botanical>Asclepias tuberosa</botanical>
<zone>Annual</zone>
<colorCode>FFFFFF</colorCode>
<light>Sunny</light>
<price>2.78</price>
<availability>06/30/2006</availability>
<indoor>false</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>27</id>
<common>Cinquefoil</common>
<botanical>Potentilla</botanical>
<zone>Annual</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>7.06</price>
<availability>05/25/2006</availability>
<indoor>true</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>28</id>
<common>Primrose</common>
<botanical>Oenothera</botanical>
<zone>3 - 5</zone>
<colorCode>FFFFFF</colorCode>
<light>Sunny</light>
<price>6.56</price>
<availability>01/30/2006</availability>
<indoor>false</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>29</id>
<common>Gentian</common>
<botanical>Gentiana</botanical>
<zone>4</zone>
<colorCode>EEEEEE</colorCode>
<light>Sun or Shade</light>
<price>7.81</price>
<availability>05/18/2006</availability>
<indoor>false</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>30</id>
<common>Blue Gentian</common>
<botanical>Gentiana</botanical>
<zone>4</zone>
<colorCode>EEEEEE</colorCode>
<light>Sun or Shade</light>
<price>8.56</price>
<availability>05/02/2006</availability>
<indoor>false</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>31</id>
<common>Jacob's Ladder</common>
<botanical>Polemonium caeruleum</botanical>
<zone>Annual</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>9.26</price>
<availability>02/21/2006</availability>
<indoor>true</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>36</id>
<common>Greek Valerian</common>
<botanical>Polemonium caeruleum</botanical>
<zone>Annual</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>4.36</price>
<availability>07/14/2006</availability>
<indoor>true</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>32</id>
<common>California Poppy</common>
<botanical>Eschscholzia californica</botanical>
<zone>Annual</zone>
<colorCode>FFFFFF</colorCode>
<light>Sunny</light>
<price>7.89</price>
<availability>03/27/2006</availability>
<indoor>false</indoor>
<status>WaitCheck</status>
</plant>
<plant>
<id>33</id>
<common>Shooting Star</common>
<botanical>Dodecatheon</botanical>
<zone>Annual</zone>
<colorCode>E7E7E7</colorCode>
<light>Mostly Shady</light>
<price>8.60</price>
<availability>05/13/2006</availability>
<indoor>true</indoor>
<status>Checked</status>
</plant>
<plant>
<id>34</id>
<common>Snakeroot</common>
<botanical>Cimicifuga</botanical>
<zone>Annual</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>5.63</price>
<availability>07/11/2006</availability>
<indoor>true</indoor>
<status>Checked</status>
</plant>
<plant>
<id>35</id>
<common>Cardinal Flower</common>
<botanical>Lobelia cardinalis</botanical>
<zone>2</zone>
<colorCode>E1E1E1</colorCode>
<light>Shade</light>
<price>3.02</price>
<availability>02/22/2006</availability>
<indoor>true</indoor>
<status>Checked</status>
</plant>
</catalog>
说明:
- <status> 节点表示数据状态。
定义数据类
该类用于读取数据 XML 文件,并获得指定页的数据。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Web;
using System.Xml;
using Ext.Net;
using System.Linq;
namespace ExtNetDynamicButton
{
public class MyPlant
{
public MyPlant()
{ }
public MyPlant(bool indoor, DateTime availability, decimal price, string light, string zone, string botanical, string common, string id, ButtonType status)
{
this.Indoor = indoor;
this.Availability = availability;
this.Price = price;
this.Light = light;
this.Zone = zone;
this.Botanical = botanical;
this.Common = common;
this.Id = id;
this.Status = status;
}
public string Id { get; set; }
public string Common { get; set; }
public string Botanical { get; set; }
public string Zone { get; set; }
public string ColorCode { get; set; }
public string Light { get; set; }
public decimal Price { get; set; }
public DateTime Availability { get; set; }
public bool Indoor { get; set; }
public ButtonType Status { get; set; }
public static List<MyPlant> MyPlants
{
get
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(HttpContext.Current.Server.MapPath("MyPlants.xml"));
List<MyPlant> data = new List<MyPlant>();
IFormatProvider culture = new CultureInfo("en-US", true);
foreach (XmlNode plantNode in xmlDoc.SelectNodes("catalog/plant"))
{
MyPlant plant = new MyPlant();
plant.Id = plantNode.SelectSingleNode("id").InnerText;
plant.Common = plantNode.SelectSingleNode("common").InnerText;
plant.Botanical = plantNode.SelectSingleNode("botanical").InnerText;
plant.Zone = plantNode.SelectSingleNode("zone").InnerText;
plant.ColorCode = plantNode.SelectSingleNode("colorCode").InnerText;
plant.Light = plantNode.SelectSingleNode("light").InnerText;
plant.Price = decimal.Parse(plantNode.SelectSingleNode("price").InnerText, culture);
plant.Availability = DateTime.Parse(plantNode.SelectSingleNode("availability").InnerText, culture);
plant.Indoor = bool.Parse(plantNode.SelectSingleNode("indoor").InnerText);
plant.Status = (ButtonType)Enum.Parse(typeof(ButtonType), plantNode.SelectSingleNode("status").InnerText, true);
data.Add(plant);
}
return data;
}
}
public static IEnumerable<MyPlant> PlantsPaging(int startRec, int MaxRec, ref int total, string status)
{
List<MyPlant> data = MyPlant.MyPlants;
IEnumerable<MyPlant> queryAll = data.FindAll(r => r.Status == (ButtonType)Enum.Parse(typeof(ButtonType), status, true));
IEnumerable<MyPlant> query = queryAll.Skip(startRec).Take(MaxRec);
total = queryAll.Count();
return query;
}
}
}
说明:
- 简单起见,用 LINQ 分页。
页面文件
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="ExtNetDynamicButton.WebForm1" %>
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<ext:ResourcePlaceHolder ID="ResourcePlaceHolder1" runat="server" Mode="Script" />
<script type="text/javascript">1:
2: // ButtonList 控制3: Ext.onReady(function() {4: Ext.net.DirectMethods.GetUserButtons(
5: {
6: success: function(result) {7: setButtonList(result);
8: },
9: failure: function(result) {10: Ext.Msg.alert('信息', '网络慢请稍后重试.');11: }
12: })
13:
14: });
15:
16: var ToolBarButtonList = function(id, actionType) {17: Ext.net.DirectMethods.ToolBar_ButtonListOnClick(id, actionType,
18: {
19: success: function(result) {20: GridPanel1.store.load();
21: setButtonList(result);
22:
23: },
24: failure: function(result) {25: Ext.Msg.alert('信息', '网络慢请稍后重试.');26: }
27: });
28: };
29: var setButtonList = function(actionParas) {30: var cm = GridPanel1.getColumnModel();31: var actionListIdx = cm.getIndexById('GridActionList');32: var cmActionList = cm.columns[actionListIdx];33: // 禁用所有34: for (var i = 0; i < cmActionList.commands.length; i++) {35: cmActionList.commands[i].hidden = true;36: }
37: for (var i = 0; i < cmActionList.groupCommands.length; i++) {38: cmActionList.groupCommands[i].hidden = true;39: }
40: // 启用该启用41: var paras = Ext.decode(actionParas);42: var actionType = paras.ButtonStatus;43: var groupRowActions = paras.GroupRowActions;44: var rowActions = paras.RowActions;45: if (rowActions.length > 0) {46: Ext.each(rowActions,
47: function(action) {48: for (var i = 0; i < cmActionList.commands.length; i++) {49: if (action.Name == cmActionList.commands[i].text)50: cmActionList.commands[i].hidden = false;51: }
52: },
53: this, false);54: }
55: if (groupRowActions.length > 0) {56: Ext.each(groupRowActions,
57: function(action) {58: for (var i = 0; i < cmActionList.groupCommands.length; i++) {59: if (action.Name == cmActionList.groupCommands[i].text)60: cmActionList.groupCommands[i].hidden = false;61: }
62: },
63: this, false);64: }
65: }
66:
</script>1:
2:
3: <script type="text/javascript">4: Actions = {
5: rowCommand: function(command, record) {6: Ext.Msg.alert(command, record.data.Common);
7:
8: },
9: groupCommand: function(command, records) {10: var ids = [];11: Ext.each(records, function(r) { ids.push(r.data.Common, ids); });12: Ext.Msg.alert(command, ids.join());
13: }
14: }
15:
</script>
</head>
<body>
<form id="form1" runat="server">
<ext:ResourceManager ID="ResourceManager1" runat="server" />
<ext:Store ID="Store1" runat="server" OnRefreshData="MyRefreshData" GroupField="Light"
AutoLoad="true">
<Proxy>
<ext:PageProxy>
</ext:PageProxy>
</Proxy>
<Reader>
<ext:JsonReader IDProperty="Id">
<Fields>
<ext:RecordField Name="Id" />
<ext:RecordField Name="Common" />
<ext:RecordField Name="Botanical" />
<ext:RecordField Name="Zone" Type="Int" />
<ext:RecordField Name="ColorCode" />
<ext:RecordField Name="Light" />
<ext:RecordField Name="Price" Type="Float" />
<ext:RecordField Name="Availability" Type="Date" />
<ext:RecordField Name="Indoor" Type="Boolean" />
</Fields>
</ext:JsonReader>
</Reader>
</ext:Store>
<ext:GridPanel ID="GridPanel1" runat="server" Width="800" AutoHeight="true" StoreID="Store1"
Title="植物">
<TopBar>
<ext:Toolbar ID="Toolbar_Status" runat="server">
</ext:Toolbar>
</TopBar>
<ColumnModel ID="ColumnModel1" runat="server">
<Columns>
<ext:Column Header="Key" DataIndex="Id" />
<ext:Column Header="Common Name" DataIndex="Common" />
<ext:Column Header="Light" DataIndex="Light" />
<ext:Column Header="Price" DataIndex="Price" Align="right" Groupable="false" />
<ext:Column Header="Price" DataIndex="Price" Align="right" Groupable="false" />
<ext:DateColumn Header="Available" DataIndex="Availability" Groupable="false" Format="yyyy-MM-dd" />
<ext:CommandColumn ColumnID="GridActionList" Header="操作项" Width="200">
<GroupCommands>
<ext:GridCommand Icon="Add" CommandName="Add" Text="添加" HideMode="Visibility">
</ext:GridCommand>
</GroupCommands>
<Commands>
<ext:GridCommand Icon="Accept" CommandName="Commit" Text="提交">
</ext:GridCommand>
<ext:GridCommand Icon="DatabaseDelete" CommandName="Delete" Text="删除">
</ext:GridCommand>
<ext:GridCommand Icon="DatabaseEdit" CommandName="Edit" Text="修改">
</ext:GridCommand>
<ext:GridCommand Icon="Accept" CommandName="Check" Text="审核">
</ext:GridCommand>
<ext:GridCommand Icon="Decline" CommandName="TurnBack" Text="取消">
</ext:GridCommand>
</Commands>
</ext:CommandColumn>
</Columns>
</ColumnModel>
<Listeners>
<Command Handler="Actions.rowCommand(command, record);" />
<GroupCommand Handler="Actions.groupCommand(command, records);" />
</Listeners>
<SelectionModel>
<ext:RowSelectionModel ID="RowSelectionModel1" runat="server">
</ext:RowSelectionModel>
</SelectionModel>
<View>
<ext:GroupingView ID="GroupingView1" runat="server" ForceFit="true" />
</View>
<BottomBar>
<ext:PagingToolbar ID="PagingToolbar1" runat="server" PageSize="10" HideRefresh="true" />
</BottomBar>
</ext:GridPanel>
</form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Reflection;
using Ext.Net;
namespace ExtNetDynamicButton
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
this.StatusButton = ButtonType.WaitCommit.ToString();
this.StatusButtonId = this.Buttons[0].Id;
var buttonStatus = MyButton.ButtonList.FindAll(p => p.ParentId == -1);
foreach (var button in buttonStatus)
{
Ext.Net.Button btn = new Ext.Net.Button();
btn.Text = button.Name;
btn.CommandName = button.ButtonAction.ToString();
btn.Icon = Ext.Net.Icon.Add;
btn.Listeners.Click.Handler = "ToolBarButtonList('" + button.Id + "','" + button.ButtonType.ToString() + "')";
this.Toolbar_Status.Items.Add(btn);
}
}
}
protected void MyRefreshData(object sender, StoreRefreshDataEventArgs e)
{
IEnumerable<MyPlant> data = null;
int total = 0;
data = MyPlant.PlantsPaging(e.Start <= 0 ? 0 : e.Start, this.PagingToolbar1.PageSize, ref total, this.StatusButton);
e.Total = total;
this.Store1.DataSource = data;
this.Store1.DataBind();
}
[DirectMethod]
public string ToolBar_ButtonListOnClick(int id, string dataStatus)
{
this.StatusButton = dataStatus;
return GetUserButtons(id, (ButtonType)Enum.Parse(typeof(ButtonType), dataStatus, true));
}
[DirectMethod]
public string GetUserButtons()
{
return GetUserButtons(this.StatusButtonId, ButtonType.WaitCommit);
}
private string GetUserButtons(int id, ButtonType status)
{
var buttonsAll = this.Buttons.FindAll(b => b.ParentId == id);
var buttonGcmd = buttonsAll.FindAll(b => b.ButtonType == ButtonType.GroupCommand);
MyButton[] buttonArrGcmd = buttonGcmd.ToArray();
var buttonRcmd = buttonsAll.FindAll(b => b.ButtonType == ButtonType.Command);
MyButton[] buttonArrRcmd = buttonRcmd.ToArray();
var result = new
{
ButtonStatus = status.ToString(),
GroupRowActions = buttonArrGcmd,
RowActions = buttonArrRcmd
};
return JSON.Serialize(result);
}
#region 视图变量
public string StatusButton
{
get { return (string)this.ViewState["StatusButton"] ?? "-1"; }
set { this.ViewState["StatusButton"] = value; }
}
public int StatusButtonId
{
get { return this.ViewState["StatusButtonId"] == null ? -1 : Convert.ToInt16(this.ViewState["StatusButtonId"].ToString()); }
set { this.ViewState["StatusButtonId"] = value; }
}
public List<MyButton> Buttons
{
get
{
if (this.ViewState["Buttons"] == null)
{
List<MyUser> users = MyUser.UsersList;
List<MyButton> userButtons = users.Find(u => u.Name == this.UserName).Buttons;
this.ViewState["Buttons"] = userButtons;
return (List<MyButton>)this.ViewState["Buttons"];
}
return (List<MyButton>)this.ViewState["Buttons"];
}
}
public string UserName
{
get { return (string)Session["UserName"] ?? "u1"; }
set { Session["UserName"] = value; }
}
#endregion
}
}
备注:
本演示解决问题如下三点:
- 根据权限动态创建按钮。包括数据状态按钮、grid 组按钮、grid 行按钮;
- 服务器端分页。任何一个点击按钮的操作,都需要根据当前的数据状态重新向 grid 加载数据;
- 只有点击“数据状态按钮”时,才会刷新整个页面,因为要重新呈现操作按钮,而其他情况只是局部刷新。也就是说,改变数据状态时,会看到页面闪了一下,其他情况,页面都不会闪。
本解决方案的改进
如果仔细看下本例,其实有好几处可以改进的地方。在本解决方案是将全部按钮在页面中标记出来,设置按钮时,先全部设置不可见,再根据权限设置相应的按钮可见。
但是你可以 Ext.Net 在前端用脚本动态去创建按钮。这是其一。也可以在 Ext.onReady 中,获得用户权限后,设置脚本 Actions 类的全局变量,然后再动态创建。
比如,在本例基础上,可以做如下改进:
<script type="text/javascript">
var actions;
Ext.onReady(function() {
Ext.net.DirectMethods.GetUserButtons(
{
success: function(result) {
var o = Ext.decode(result);
actions = o.Actions;
var cm = GridPanel1.getColumnModel();
var gridCmActionsIdx = cm.getIndexById('GridActionList');
gridCmActions = cm.columns[gridCmActionsIdx];
setActionsHide();
setActionsShow(o.Id);
},
failure: function(result) {
Ext.Msg.alert('信息', '网络慢请稍后重试.');
}
})
});
var ToolBarButtonList = function(id, actionType) {
Ext.net.DirectMethods.ToolBar_ButtonListOnClick(id, actionType,
{
success: function(result) {
GridPanel1.store.load();
setActionsHide();
setActionsShow(result);
},
failure: function(result) {
Ext.Msg.alert('信息', '网络慢请稍后重试.');
}
});
};
// 禁用所有
var setActionsHide = function() {
for (var i = 0; i < gridCmActions.commands.length; i++) {
gridCmActions.commands[i].hidden = true;
}
for (var i = 0; i < gridCmActions.groupCommands.length; i++) {
gridCmActions.groupCommands[i].hidden = true;
}
};
// 启用该启用
var setActionsShow = function(id) {
Ext.each(actions, function(action) {
if (action.ParentId == id) {
switch (action.ButtonType) {
case "GroupCommand":
for (var i = 0; i < gridCmActions.groupCommands.length; i++) {
if (action.Name == gridCmActions.groupCommands[i].text) {
gridCmActions.groupCommands[i].hidden = false;
break;
}
}
break;
case "Command":
for (var i = 0; i < gridCmActions.commands.length; i++) {
if (action.Name == gridCmActions.commands[i].text) {
gridCmActions.commands[i].hidden = false;
break;
}
}
break;
}
}
}, this, false);
};
</script>
[DirectMethod]
public string ToolBar_ButtonListOnClick(int id, string dataStatus)
{
this.StatusButtonId = id;
this.StatusButton = dataStatus;
return this.StatusButtonId.ToString();
}
[DirectMethod]
public string GetUserButtons()
{
MyButton[] buttonAllArr = this.Buttons.ToArray();
var result = new
{
Id = this.StatusButtonId,
Status = this.StatusButton.ToString(),
Actions = buttonAllArr
};
return JSON.Serialize(result);
}
说明:
- 替换本改进的相应脚本和后台方法;
- 这个改进减少了数据传输量。只在 Ext.onReady 事件里获取用户的按钮,并设置脚本的全局变量。之后,当改变数据状态时,使用该全局变量,设置按钮。而之前的例子是,每次改变数据状态,调用后台时,将相应的用户按钮回调给前台脚本。
返回 Ext.Net_演示为权限控制动态创建按钮的一个解决方案-01_2
修改记录
- 第一次 2012-04-15 [BUG] 隐藏组按钮页面缺失问题,如下图所示:
- 第二次 2012-04-16 [ADD] 改进演示