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 节点的属性 idtextparentidbuttontypebuttonaction 分别表示按钮的编号、名称、父编号、按钮类型、按钮动作。如,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 文件

假设有三个用户 u1u2admin,授权后如下所示:

<?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
    }
}

备注:

本演示解决问题如下三点:

  1. 根据权限动态创建按钮。包括数据状态按钮、grid 组按钮、grid 行按钮;
  2. 服务器端分页。任何一个点击按钮的操作,都需要根据当前的数据状态重新向 grid 加载数据;
  3. 只有点击“数据状态按钮”时,才会刷新整个页面,因为要重新呈现操作按钮,而其他情况只是局部刷新。也就是说,改变数据状态时,会看到页面闪了一下,其他情况,页面都不会闪。

 

下载 Demo

 

本解决方案的改进

如果仔细看下本例,其实有好几处可以改进的地方。在本解决方案是将全部按钮在页面中标记出来,设置按钮时,先全部设置不可见,再根据权限设置相应的按钮可见。

但是你可以 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 事件里获取用户的按钮,并设置脚本的全局变量。之后,当改变数据状态时,使用该全局变量,设置按钮。而之前的例子是,每次改变数据状态,调用后台时,将相应的用户按钮回调给前台脚本。

 

下载 Demo

 

返回 Ext.Net_演示为权限控制动态创建按钮的一个解决方案-01_2

 

 

修改记录

  • 第一次 2012-04-15 [BUG] 隐藏组按钮页面缺失问题,如下图所示:

2012-04-15_235702

  • 第二次 2012-04-16 [ADD] 改进演示
posted @ 2012-04-15 00:33  船长&CAP  阅读(958)  评论(0编辑  收藏  举报
免费流量统计软件