• Ext.Net 1.2.0_利用 Ext.Net 自定义 GridPanel Ajax 控件


    本文内容

    • 概述
    • 演示:利用 Ext.Net 自定义简单的 GridPanel 控件
    •     不封装的程序
    •     封装后的程序
    • 修改记录

    概述

    最近研究 Ext.Net 的 Demo,看到 SimpleTask 例子,该例子利用 Ext.Net 自己封装了三个控件来使用,感觉不错。

    其实,这种方式在 .NET 里很常见,但是由于 Ext.Net 自定义的 Ajax 控件,综合使用了 DOM、CSS 和 JavaScript,还是有一定难度。但是从另外一个角度来看,却比 .NET 简单很多。是不是很奇怪,因为 Ext.Net 有现成的操作 DOM、CSS 和 JavaScript 的框架,你只需要将它们集成到一起。

    演示:利用 Ext.Net 自定义 GridPanel 控件

    本节演示利用 Ext.Net 自定义简单的 GridPanel 控件。

    不封装的程序

    首先看看,在不封装的情况下,使用 GridPanel 控件。用于改变某行、或某列的的式样。代码如下:

    <%@ Page Language="C#" %>
     
    <%@ 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>Ext.Net GridPanel 改变某行、或某列的的式样</title>
        <style type="text/css">
            .indoor-t
            {
                color: #fb223a;
            }
            .indoor-f
            {
                text-decoration: line-through;
                color: gray;
            }
        </style>
     
        <script type="text/javascript">
       1:  
       2:         // 改变行式样
       3:         var getRowClass = function(r) {
       4:             var d = r.data;
       5:  
       6:             if (d.Indoor) {
       7:                 return "indoor-t";
       8:             }
       9:             else {
      10:                 return "indoor-f";
      11:             }
      12:         };
      13:         // 改变列式样
      14:         var template = '<span style="color:{0};">{1}</span>';
      15:         var changePriceStyle = function(value) {
      16:             return String.format(template, (value >= 5) ? "green" : "red", value);
      17:         }; 
      18:     
    </script>
       1:  
       2:  
       3:     <script runat="server">
       4:         protected void Chg_Click(object sender, DirectEventArgs e)
       5:         {
       6:             string Id = e.ExtraParams["Id"];
       7:             string common = e.ExtraParams["Common"];
       8:             bool indoor = Convert.ToBoolean(e.ExtraParams["Indoor"].ToString());
       9:  
      10:             // TODO 
      11:             // Server-Side
      12:  
      13:             this.Store1.SuspendEvents(false);
      14:  
      15:             this.Store1.UpdateRecordField((object)Id, "Indoor", !indoor);
      16:             this.Store1.ResumeEvents();
      17:             this.Store1.FireEvent("datachanged", new JRawValue(this.Store1.ClientID));
      18:         }        
      19:     
    </script>
     
    </head>
    <body>
        <form id="form1" runat="server">
        <ext:ResourceManager ID="ResourceManager1" runat="server" />
        <ext:GridPanel ID="GridPanel1" runat="server" Width="600" Height="500" AutoExpandColumn="Common"
            Title="植物" Frame="true">
            <Store>
                <ext:Store ID="Store1" runat="server" GroupField="Light">
                    <Proxy>
                        <ext:HttpProxy Method="GET" Url="Data/PlantService.asmx/Plants" />
                    </Proxy>
                    <Reader>
                        <ext:XmlReader Record="Plant" IDPath="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:XmlReader>
                    </Reader>
                    <SortInfo Field="Common" Direction="ASC" />
                </ext:Store>
            </Store>
            <ColumnModel ID="ColumnModel1" runat="server">
                <Columns>
                    <ext:Column ColumnID="Id" Header="Key" DataIndex="Id" Width="10" />
                    <ext:Column ColumnID="Common" Header="Common Name" DataIndex="Common" Width="220" />
                    <ext:Column Header="Light" DataIndex="Light" Width="130" />
                    <ext:Column Header="Price" DataIndex="Price" Width="70" Align="right" Groupable="false">
                        <Renderer Format="UsMoney" />
                    </ext:Column>
                    <ext:Column Header="Price" DataIndex="Price" Width="70" Align="right" Groupable="false">
                        <Renderer Fn="changePriceStyle" />
                    </ext:Column>
                    <ext:DateColumn Header="Available" DataIndex="Availability" Width="95" Groupable="false"
                        Format="yyyy-MM-dd" />
                    <ext:Column Header="Indoor?" DataIndex="Indoor" Width="55" />
                    <ext:ImageCommandColumn Width="110">
                        <Commands>
                            <ext:ImageCommand CommandName="Change" Icon="TableEdit" Text="改变">
                                <ToolTip Text="改变" />
                            </ext:ImageCommand>
                        </Commands>
                    </ext:ImageCommandColumn>
                </Columns>
            </ColumnModel>
            <DirectEvents>
                <Command OnEvent="Chg_Click">
                    <ExtraParams>
                        <ext:Parameter Name="Id" Value="record.id" Mode="Raw">
                        </ext:Parameter>
                        <ext:Parameter Name="Common" Value="record.data.Common" Mode="Raw">
                        </ext:Parameter>
                        <ext:Parameter Name="Indoor" Value="record.data.Indoor" Mode="Raw">
                        </ext:Parameter>
                    </ExtraParams>
                </Command>
            </DirectEvents>
            <LoadMask ShowMask="true" />
            <SelectionModel>
                <ext:RowSelectionModel ID="RowSelectionModel1" runat="server" />
            </SelectionModel>
            <View>
                <ext:GroupingView ID="GroupingView1" HideGroupedColumn="true" runat="server" ForceFit="true"
                    StartCollapsed="true">
                    <GetRowClass Fn="getRowClass" />
                </ext:GroupingView>
            </View>
            <Buttons>
                <ext:Button ID="btnToggleGroups" runat="server" Text="展开/收起分组" Icon="TableSort" Style="margin-left: 6px;"
                    AutoPostBack="false">
                    <Listeners>
                        <Click Handler="#{GridPanel1}.getView().toggleAllGroups();" />
                    </Listeners>
                </ext:Button>
            </Buttons>
        </ext:GridPanel>
        </form>
    </body>
    </html>

    运行界面:

    {8%3N_(QLC9JOL(I14$FUMC

    图1 不封装的 GridPanel

    • 当 Indoor 列为 true 时,整个行是红色;否则为该行添加删除线。
    • 当第二个 Price 大于5时,该列为红色;否则为绿色。
    • 点击“改变”按钮,会改变行式样。

    说明:

    1,首先看下 HTML 标记,值得注意的有以下几点:

    • Store 通过 WebService 获得数据。Ext.Net 若想使用 WebService,要在 Web.Config  文件的 <system.web> 节添加如下内容。如何获得数据无所谓。
    <webServices>
      <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
      </protocols>
    </webServices>
    • Store 还规定了 GridPanel 分组的字段,"GroupField="Light"。并且规定 Store 的主键,"<ext:XmlReader Record="Plant" IDPath="Id">";

    2,服务器端事件。为了改变某行的式样,需要根据行ID,更新 Store 的记录,并触发 Store 的 datachanged 事件。

    封装后的程序

    接下来,看看如何封装这个功能。先看界面,然后再说明如何实现。

    <%@ Page Language="C#" %>
     
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    <%@ Register Assembly="ExtNetCustomControl" Namespace="ExtNetCustomControl.MyCustom"
        TagPrefix="MyControl" %>
    <!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>Ext.Net GridPanel 改变某行、或某列的的式样</title>
        <ext:ResourcePlaceHolder ID="ResourcePlaceHolder1" runat="server" Mode="ScriptFiles" />
        <link href="resources/main.css" rel="stylesheet" type="text/css" />
        <style type="text/css">
            .indoor-t
            {
                color: #fb223a;
            }
            .indoor-f
            {
                text-decoration: line-through;
                color: gray;
            }
        </style>
     
        <script src="resources/myGrid.js" type="text/javascript"></script>
     
    </head>
    <body>
        <form id="form1" runat="server">
        <ext:ResourceManager ID="ResourceManager1" runat="server" InitScriptMode="Linked"
            DirectEventUrl="MyCustomGrid.aspx" RemoveViewState="true" IDMode="Explicit" />
        <ext:Panel ID="Panel1" runat="server" Width="600" Height="600" AutoScroll="true">
            <Items>
                <MyControl:MyGrid ID="MyGrid1" runat="server" AutoHeight="true" />
            </Items>
        </ext:Panel>
        </form>
    </body>
    </html>

    说明:

    1,这个界面比之前简单多了。

    定义 MyGrid 分部类,分别实现控件的 UI 和逻辑代码,如下所示:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Xml.Serialization;
    using Ext.Net;
    using Newtonsoft.Json;
     
    namespace ExtNetCustomControl.MyCustom
    {
        public partial class MyGrid : GridPanel
        {
            private Store store;
     
            public MyGrid()
            {
                this.Title = "植物";
                this.Width = System.Web.UI.WebControls.Unit.Pixel(600);
                this.Height = System.Web.UI.WebControls.Unit.Pixel(500);
                this.Frame = true;
                this.AutoExpandColumn = "Common";
     
                this.LoadMask.ShowMask = true;
     
                this.SelectionModel.Add(new RowSelectionModel());
     
                this.View.Add(new GroupingView
                {
                    HideGroupedColumn = true,
                    ForceFit = true,
                    StartCollapsed = true,
                    GetRowClass = { Fn = MyGrid.SCOPE + ".getRowClass" }
                });
     
                this.BuildStore();
                this.BuildColumnModel();
                this.InitLogic();
            }
     
            private void BuildColumnModel()
            {
                ColumnModel cm = this.ColumnModel;
                cm.Columns.Add(new Column
                   {
                       ColumnID = "Id",
                       Header = "Key",
                       Width = 10,
                       DataIndex = "Id"
                   });
     
                cm.Columns.Add(new Column
                   {
                       ColumnID = "Common",
                       Header = "Common Name",
                       Width = 220,
                       DataIndex = "Common"
                   });
     
                cm.Columns.Add(new Column
                   {
                       Header = "Light",
                       Width = 130,
                       DataIndex = "Light"
                   });
     
                cm.Columns.Add(new Column
                   {
                       Header = "Price",
                       Width = 70,
                       DataIndex = "Price",
                       Align = Ext.Net.Alignment.Right,
                       Groupable = false,
                       Renderer = new Renderer { Format = Ext.Net.RendererFormat.UsMoney }
                   });
     
                cm.Columns.Add(new Column
                {
                    Header = "Price",
                    Width = 70,
                    DataIndex = "Price",
                    Align = Ext.Net.Alignment.Right,
                    Groupable = false,
                    Renderer = new Renderer { Fn = MyGrid.SCOPE + ".changePriceStyle" }
                });
                cm.Columns.Add(new DateColumn
                {
                    Header = "Available",
                    Width = 95,
                    DataIndex = "Availability",
                    Format = "yyyy-MM-dd",
                    Groupable = false
                });
                cm.Columns.Add(new Column
                {
                    Header = "Indoor?",
                    Width = 55,
                    DataIndex = "Indoor"
                });
                cm.Columns.Add(new ImageCommandColumn
                {
                    Commands = 
                    { 
                        new ImageCommand 
                        { 
                            CommandName = "Change", 
                            Icon = Icon.TableEdit, 
                            Text = "改变"
                        } 
                    }
                });
            }
     
            private void BuildStore()
            {
                this.store = new Store
                 {
                     Reader =
                     {
                         new Ext.Net.XmlReader
                         {
                             Record="Plant",
                             IDPath="Id",
                             Fields =
                             {
                                 new RecordField("Id"),
                                 new RecordField("Common"),
                                 new RecordField("Botanical"),
                                 new RecordField("Zone",RecordFieldType.Int),
                                 new RecordField("ColorCode"),
                                 new RecordField("Light"),
                                 new RecordField("Price", RecordFieldType.Float),
                                 new RecordField("Availability", RecordFieldType.Date),
                                 new RecordField("Indoor", RecordFieldType.Boolean)
                             }
                         }
                     },
                     SortInfo =
                     {
                         Field = "Common",
                         Direction = SortDirection.ASC
                     },
                     GroupField = "Light",
                     Proxy =
                     {
                         new HttpProxy { Method=Ext.Net.HttpMethod.GET,Url="Data/PlantService.asmx/Plants"}
                     }
                 };
                this.Store.Add(this.store);
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
     
    using Ext.Net.Utilities;
    using Ext.Net;
     
    namespace ExtNetCustomControl.MyCustom
    {
        [DirectMethodProxyID(IDMode = DirectMethodProxyIDMode.None)]
        public partial class MyGrid
        {
            public const string SCOPE = "MyCustom.MyGrid";
     
            private void InitLogic()
            {
                this.Listeners.Render.Fn = MyGrid.SCOPE + ".init";
                this.Listeners.Render.Scope = MyGrid.SCOPE;
     
                ComponentDirectEvent command = this.DirectEvents.Command;
                command.Event += Command_Event;
                command.ExtraParams.Add(new Parameter("Id", "record.id", ParameterMode.Raw));
                command.ExtraParams.Add(new Parameter("Common", "record.data.Common", ParameterMode.Raw));
                command.ExtraParams.Add(new Parameter("Indoor", "record.data.Indoor", ParameterMode.Raw));
     
                Ext.Net.Button button = new Button();
                button.ID = "btnToggleGroups";
                button.Text = "展开/收起分组";
                button.Icon = Icon.TableSort;
                button.AutoPostBack = false;
                button.Listeners.Click.Handler = MyGrid.SCOPE + ".toggleAllGroups();";
                this.Buttons.Add(button);
            }
            protected void Command_Event(object sender, DirectEventArgs e)
            {
                string Id = e.ExtraParams["Id"];
                string common = e.ExtraParams["Common"];
                bool indoor = Convert.ToBoolean(e.ExtraParams["Indoor"].ToString());
     
                // TODO 
                // Server-Side
     
                this.store.SuspendEvents(false);
     
                this.store.UpdateRecordField((object)Id, "Indoor", !indoor);
                this.store.ResumeEvents();
                this.store.FireEvent("datachanged", new JRawValue(this.store.ClientID));
            }
     
            protected override void OnLoad(EventArgs e)
            {
                if (!Ext.Net.X.IsAjaxRequest)
                {
                    this.ResourceManager.AddDirectMethodControl(this);
                }
            }
        }
    }

    说明:

    1. 以上两段代码实现的是同一个类,分别用来实现控件的UI和逻辑。UI部分完成创建控件的标记;逻辑部分完成控件的事件,包括客户端事件和服务器端事件;
    2. 注意 InitLogic 函数的前两行。当该控件实例化、并呈现后,调用客户端脚本 MyCustom.MyGrid.init 函数,用该实例化的控件初始化客户端脚本 MyGrid 对象的全局变量 grid。同时,还设置了该控件的作用域。

    但光有这个类还不够,还要跟它配合的客户端脚本,如下所示:

    Ext.ns("MyCustom");
     
    // ------------------MyGrid----------------------------------
    MyCustom.MyGrid = {
        init: function(grid) {
            this.grid = grid;
        },
     
        getRowClass: function(r) {
            var d = r.data;
            if (d.Indoor) {
                return "indoor-t";
            }
            else {
                return "indoor-f";
            }
            return "";
        },
     
        changePriceStyle: function(value) {
            var template = '<span style="color:{0};">{1}</span>';
            return String.format(template, (value >= 5) ? "green" : "red", value);
        },
     
        toggleAllGroups: function() {
            this.grid.getView().toggleAllGroups();
        }
    };

    说明:

    1. 该客户端脚本,创建了一个命名空间 MyCustom,并在该命名空间里创建 MyGrid 对象。
    2. 值得注意的是 init 函数。当在页面引入 <%@ Register Assembly="ExtNetCustomControl" Namespace="ExtNetCustomControl.MyCustom" TagPrefix="MyControl" %> 标记,那么 Web 应用程序运行时,自定义控件 MyGrid 被实例化。在客户端呈现后,会调用客户端脚本 MyCustom.MyGrid.init 方法,从而初始化 MyCustom.MyGrid 的 grid 属性,以便之后在客户端用脚本操作该自定义控件。
    3. 另外,MyCustom.MyGrid 的 grid 属性被初始化后,它是 Ext.Net.GridPanel 类的一个实例。

    修改记录

    • 第一次 2011-12-23 [UPDATE] 封装后的程序小节的说明部分。

    下载 Demo

  • 相关阅读:
    MySQL binlog 组提交与 XA(两阶段提交)
    mydumper 安装报错处理
    安装 gcc-c++ 时报错和原有 gcc 版本冲突
    mysql / mysqld_safe / mysqld 常见错误处理
    Linux 内核日志——dmesg
    Java中的Atomic包
    JAVA NIO中的Channels和Buffers
    字节流InputStream/OutputStream
    字符输出流Writer简要概括
    字符输入流Reader简要概括
  • 原文地址:https://www.cnblogs.com/liuning8023/p/2204208.html
Copyright © 2020-2023  润新知