支持多选的datagrid控件的源代码

这是支持多选的datagrid控件的源代码,只包含关键的源代码,所有的源码请到msdn下载:

namespace BWSLib
{
    public class MultiGrid : DataGrid
    {
        // Constructor that sets some styles and graphical properties   
        public MultiGrid()
        {
            AllowMultiSelect = false;
            AllowMultiSelectFooter = false;

            // Set event handlers
            Init += new EventHandler(OnInit);
            ItemCreated += new DataGridItemEventHandler(OnItemCreated);
        }

        // PROPERTY: SelectedItems
        public ArrayList SelectedItems
        {
            get
            {
                if (!AllowMultiSelect)    return null;

                ArrayList a = new ArrayList();
                foreach(DataGridItem dgi in Items)
                {
                    CheckBox cb = (CheckBox) dgi.Cells[0].Controls[0];
                    if (cb.Checked)
                        a.Add(dgi);
                }
                return a;
            }
        }

        // PROPERTY: AllowMultiSelect
        public bool AllowMultiSelect = false;

        // PROPERTY: AllowMultiSelectFooter
        public bool AllowMultiSelectFooter = false;

        // METHOD: ClearSelection
        public void ClearSelection()
        {
            foreach(DataGridItem dgi in Items)
            {
                CheckBox cb = (CheckBox) dgi.Cells[0].Controls[0];
                cb.Checked = false;
            }
        }

        ///////////////////////////////////////////////////////////////////
        // Event Handlers


        // EVENT HANDLER: Init           
        private void OnInit(Object sender, EventArgs e)
        {
            // Add a templated column that would allow for selection.
            // The item template contains a checkbox. It also features a
            // templated footer containing links for Unselect/Select all
            if (AllowMultiSelect)
                AddSelectColumn();
        }

        // EVENT HANDLER: Deselect
        private void OnDeselect(Object sender, EventArgs e)
        {
            ClearSelection();
        }

        // EVENT HANDLER: ItemCreated           
        private void OnItemCreated(Object sender, DataGridItemEventArgs e)
        {
            // Get the newly created item
            ListItemType itemType = e.Item.ItemType;

            ///////////////////////////////////////////////////////////////
            // FOOTER
            if (itemType == ListItemType.Footer && AllowMultiSelectFooter
                && AllowMultiSelect)
            {
                // Look for a link button called "lnkSelect" in the context
                // of the grid item that represents the footer
                LinkButton lb = (LinkButton)
                    e.Item.FindControl("lnkDeselect");

                // Now you hold the living instance of the link
                // button in the footer and can bind it to any code in the
                // context of the MultiGrid control
                lb.Click += new EventHandler(OnDeselect);
               
                // Force ShowFooter to true
                ShowFooter = true;

                // Removes all the cells but the first
                TableCell cell = e.Item.Cells[0];
                for (int i=1; i<Columns.Count; i++)
                {
                    e.Item.Cells.RemoveAt(1);
                }
                cell.ColumnSpan = Columns.Count;
            }
        }

        ///////////////////////////////////////////////////////////////////
        // Helper Functions

        private void AddSelectColumn()
        {
            // Create the new templated column
            TemplateColumn tc = new TemplateColumn();
            tc.ItemStyle.BackColor = Color.SkyBlue;
            tc.ItemTemplate = new SelectColumnTemplate();
            tc.FooterTemplate = new SelectFooterTemplate();
            Columns.AddAt(0, tc);
        }
    }

    ///////////////////////////////////////////////////////////////////////
    // Template Classes

    public class SelectColumnTemplate : ITemplate
    {
        public void InstantiateIn(Control container)
        {
            CheckBox cb = new CheckBox();
            container.Controls.Add(cb);
        }
    }

    public class SelectFooterTemplate : ITemplate
    {
        public void InstantiateIn(Control container)
        {
            LinkButton lb = new LinkButton();
            lb.Text = "Deselect all";
            lb.ID = "lnkDeselect";
            container.Controls.Add(lb);
        }
    }
}




实现ITemplate
如果你想完全地在内存中创建一个的模板,你不得不首先编码,然后实例化一个类,该类实现ITemplate接口. ITemplate接口只有一个方法,名为InstantiateIn. asp.net中所有具有template属性的服务器控件都通过这个属性暴露实现了ITemplate接口的类.这个接口简单地定义了用于组合与模板一致的子控件的实例的方法来填充容器控件.图11演示了实现itemplate接口大部分的代码,它为一个datagrid在内存中创建了一个的模板列.同样,也可以把这些代码用于datalist和repeater控件中。唯一不同的是在OnDataBinding事件处理上。类的结构你可以写成类似下面:
class LastFirstNameTemplate : ITemplate
{
  public void InstantiateIn(Control container)
  {...}

  private void BindLastName(Object s, EventArgs e)
  {...}

  private void BindFirstName(Object s, EventArgs e)
  {...}
}

Figure 11 In-memory Templated Column
// 动态的创建模板列函数
public void AddTemplateColumnFromITemplate(String strHeader)
{
    TemplateColumn bc = new TemplateColumn();
    bc.HeaderText = strHeader;
    bc.ItemTemplate = new LastFirstNameTemplate();
    grid.Columns.Add(bc);
}

// 这个类实现了一个自定义模板。新控件与容器本身的控件组合创建一个新的模板类,如// 果控件要绑定数据,你可以注册你自己的绑定处理事件(OnDataBinding事件)
public class LastFirstNameTemplate : ITemplate
{

    // Instantiate the elements of the template in the given
    // container. In this case, a DataGridItem element.

    public void InstantiateIn(Control container)
    {
        container.Controls.Add(new LiteralControl("<b>"));

        Label lblLastName = new Label();
        lblLastName.DataBinding += new EventHandler(this.BindLastName);
        container.Controls.Add(lblLastName);

        container.Controls.Add(new LiteralControl("</b>, "));

        Label lblFirstName = new Label();
        lblFirstName.DataBinding += new EventHandler(this.BindFirstName);
        container.Controls.Add(lblFirstName);
    }

    // Handler of the OnDataBinding event for the Label element
    // that renders the lastname column in the template.

    private void BindLastName(Object sender, EventArgs e)
    {
            Label l = (Label) sender;
            DataGridItem container = (DataGridItem) l.NamingContainer;
            l.Text = ((DataRowView)container.DataItem)
                ["lastname"].ToString();
    }

    // Handler of the OnDataBinding event for the Label element
    // that renders the firstname column in the template.

    private void BindFirstName(Object sender, EventArgs e)
    {
            Label l = (Label) sender;
            DataGridItem container = (DataGridItem) l.NamingContainer;
            l.Text = ((DataRowView)container.DataItem)
                ["firstname"].ToString();
    }
}
这个类可以在asp.net页的<script>部分中定义,也可以在一个单独的类文件中定义.另一种的好的方法是把这定义类的代码放在asp.net页的后台代码源文件中. 在InstantiateIn方法中,简单地创建控件的实例并把它们添加到容器控件中。对于datagrid控件来说,容器控件是一个datagriditem对象。datalist 容器控件是DataListItem对象。容器可以是任何一个实现了INamingContainer接口的类.
Label lblName = new Label();
lblName.DataBinding += new EventHandler(this.BindName);
container.Controls.Add(lblName);
  如果添加到的容器的控件集合中的控件要绑定数据源字段,那么还要为注册您自己的databinding事件处理程序。当databinding事件触发时,从数据源检索数据生成文本并刷新控件的用户界面.如果是自定义服务器控件,databinding事件处理程序需要解析服务器控件以及它所有的子控件中的所有数据绑定表达式。
void BindName(Object sender, EventArgs e)
{
  Label l = (Label) sender;
  DataGridItem container;
  container = (DataGridItem) l.NamingContainer;

  DataRowView drv;
  drv = ((DataRowView) container.DataItem);
  l.Text = drv["lastname"].ToString();
}
databinding事件处理程序完成两项任务。如果编写正确,它应该首先提取并且保持底层数据项;其次,刷新绑定控件的用户界面以反映出数据绑定。
通过sender参数可以获得相关对象的引用。包含该控件的容器可以由控件本身的namingcontainer属性返回.这时,你就有了设置和使用另一个asp.net表达式Container.DataItem所需要的所有内容。数据项的类型取决于与datagrid关联的数据源。在大多数的实际应用中,它会是DataRowview。剩下的就是访问行中的特定的列并设置控件的绑定属性。

可以多选的datagrid
在讨论完asp.net的模板时,让我举一个实际的例子详细的说明,这个例子是动态的创建一个模板列,用于多选.
<%@ Register TagPrefix="expo"
Namespace="BWSLib"
Assembly="MultiGrid" %>
•••
<expo:MultiGrid id="grid" runat="server"
    AutoGenerateColumns="false"
    AllowMultiSelect="true"
    AllowMultiSelectFooter="true"
    font-size="x-small" font-names="verdana"
    BorderStyle="solid" BorderWidth="1"
    GridLines="both">
它是一个新的控件,继承自datagrid控件。此外,它也能被实例化及像datagrid一样的配置. 这个新的控件添加了一个新的列,放了一个checkbox控件以允许选择。另外, footer被修改成用一个链接按钮用于取消选定的行。
图12列举了MultiGrid控件的新方法和属性定义。图13演示了应用该控件的情况。
Figure 12 Methods and Properties
Property/Method Description
AllowMultiSelect Boolean property that enables or disables the multi-selection feature. Defaults to False
AllowMultiSelectFooter Boolean property that enables or disables the tailor-made footer for the grid. Defaults to False. If enabled, it overrides the default footer. If disabled but the grid has a footer anyway, then the contents of this special footer are displayed as the footer of the checkbox column
SelectedItems Read-only property that returns an array with the DataGridItem objects currently selected
ClearSelection Method that clears all the currently selected items



posted on 2007-08-12 10:48  西湖浪子  阅读(342)  评论(0)    收藏  举报