如何将新的数据源添加到已经数据绑定的 CheckBoxList

How do I add new DataSource to an already Databinded CheckBoxList

我正在构建一个显示数据库项目(表、行、FK、...)的 Web 表单

我有一个 CheckBoxList of Tables (chkListTable),每当我从 chkListTable 更改 SelectedIndexChanged 时,它都会显示一个新的 CheckBoxList of Rows (chkListRow)。问题是我可以显示来自 chkListTable 的项目和 1 个选定项目。但是我不知道如何显示 chkListRow 如果选择了 chkListTable 中的多个项目。

这是我的代码:

aspx:

<div>
             <asp:Label ID="Label2" runat="server" Text="Table: "></asp:Label>
             <asp:CheckBoxList ID="chkListTable" runat="server"
                 DataTextField="name"
                 DataValueFeild="name"
                 AutoPostBack="true"
                 OnSelectedIndexChanged="chkListTable_SelectedIndexChanged">
             </asp:CheckBoxList>
        </div>
        <div>
             <asp:CheckBoxList ID="chkListRow" runat="server"
             DataTextField="COLUMN_NAME"
             DataValueField="COLUMN_NAME"
             RepeatDirection="Horizontal">
             </asp:CheckBoxList>
        </div>

aspx.cs:

protected void chkListTable_SelectedIndexChanged(object sender, EventArgs e)
    {
        tableName.Clear();
        
        foreach (ListItem item in chkListTable.Items)
        {
            if(item.Selected)
            {
                tableName.Add(item.Text.Trim());
            }    
        }

        for(int i = 0; i < tableName.Count; i++)
        {
            String query = "USE " + dbname +
                " SELECT * FROM information_schema.columns" +
                " WHERE table_name = '" + tableName[i] + "'" +
                " AND COLUMN_NAME != 'rowguid'";
            chkListRow.DataSource = Program.ExecSqlDataReader(query);
            chkListRow.DataBind(); 
            Program.conn.Close();
        }
    }

Program.cs:

public static bool Connect()
    {
        if (Program.conn != null && Program.conn.State == ConnectionState.Open)
            Program.conn.Close();
        try
        {
            Program.conn.ConnectionString = Program.constr;

            Program.conn.Open();

            return true;
        }

        catch (Exception e)
        {
            return false;
        }
    }

    public static SqlDataReader ExecSqlDataReader(String query)
    {
        SqlDataReader myreader;
        SqlCommand sqlcmd = new SqlCommand(query, Program.conn);
        sqlcmd.CommandType = CommandType.Text;
        if (Program.conn.State == ConnectionState.Closed) Program.conn.Open();
        try
        {
            myreader = sqlcmd.ExecuteReader();
            return myreader;
            myreader.Close();
        }
        catch (SqlException ex)
        {
            Program.conn.Close();
            return null;
        }
    }

我希望我的显示是这样的:

[x]Table1 [x]Table2 [ ]Table3
[ ]Row1(Table1) [ ]Row2(Table1) [ ]Row3(Table1)
[ ]Row1(Table2) [ ]Row2(Table2)

好的,这是一个相当可爱的小问题。

所以,如果我们 select 1 table,那么我们需要有一个“子”或所谓的一个复选框列表。

但是,如果我们 select 2 tables,(或 5),那么我们需要 2(或 5)个子复选框列表。

换句话说,我们不会使用相同的复选框列表(子),或者尝试“破坏”我们需要的“N”个复选框列表。

所以,这个“子”集(每个检查一个table)是事先不知道的。

那么,我们有一组“重复”的子复选框列表,对吗?

所以,我们可以(也应该)使用“中继器”。中继器所做的就是“重复”我们想要的任何内容,然后我们将 tables.

的主列表“提供”给中继器

因此,我们的标记现在将如下所示:

    <style> 
        .rBut input {margin-right: 5px; }
        .rBut label {margin-right: 15px; }
    </style>

        <asp:Label ID="Label2" runat="server" Text="Table: "></asp:Label>

        <div class="rBut">
             <asp:CheckBoxList ID="chkListTable" runat="server" 
                 DataTextField="TABLE_NAME"
                 DataValueFeild="TABLE_NAME"
                 AutoPostBack="true" RepeatDirection="Horizontal" OnSelectedIndexChanged="chkListTable_SelectedIndexChanged"                  >
             </asp:CheckBoxList>
        </div>
    </div>
    <div>

        <asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">

            <ItemTemplate>
                Table: <%# Eval("Table") %> - 
                <div class="rBut">
                    <asp:CheckBoxList ID="chkListRow" runat="server"
                     RepeatDirection="Horizontal">
                     </asp:CheckBoxList>
                </div>
            </ItemTemplate>
        </asp:Repeater>

注意第二个重复者,我们没有设置值和文本列——我们还不知道它们。您没有提到要显示哪些列,但我的大多数 table 总是在第一列有一个 PK“ID”,因此让我们将其设置为值,并显示(DataTextField,给定中的第二列table).

所以,现在我们建立第一个 select 离子的“列表”,(tables),然后将那个东西传递给转发器,它会重复。

代码现在看起来像这样:

   protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadData();                
    }

    void LoadData()
    {
        string strSQL = "SELECT TABLE_NAME FROM VideoGames.INFORMATION_SCHEMA.TABLES " +
                        "WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME";

        chkListTable.DataSource = MyRst(strSQL);
        chkListTable.DataBind();
    }
    protected void chkListTable_SelectedIndexChanged(object sender, EventArgs e)
    {
        DataTable MyTables = new DataTable();
        MyTables.Columns.Add("Table", typeof(string));

        foreach (ListItem OneTable in chkListTable.Items)
        {
            if (OneTable.Selected)
            {
                DataRow OneRow = MyTables.NewRow();
                OneRow["Table"] = OneTable.Value;
                MyTables.Rows.Add(OneRow);
            }
        }
        // ok, we have a list of tables, send that to repeater
        Repeater1.DataSource = MyTables;
        Repeater1.DataBind();
    }


    public DataTable MyRst(string strSQL)
    {
        var rst = new DataTable();
        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.VideoGames))
        {
            using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
            {
                conn.Open();
                rst.Load(cmdSQL.ExecuteReader());
            }
        }
        return rst;
    }

    protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item
            | e.Item.ItemType == ListItemType.AlternatingItem)
        {
            DataRowView rItem = e.Item.DataItem as DataRowView;  // get binding data row

            CheckBoxList chkListRow = e.Item.FindControl("chkListRow") as CheckBoxList;

            string strSQL = "SELECT * FROM " + rItem["Table"].ToString();
            DataTable MyTable = MyRst(strSQL);

            chkListRow.DataValueField = MyTable.Columns[0].ColumnName;
            chkListRow.DataTextField =  MyTable.Columns[1].ColumnName;
            chkListRow.DataSource = MyRst(strSQL);
            chkListRow.DataBind();
        }
    }

所以,现在我们看到这个:

如果我点击一个,我会看到这个:

但是,假设我点击了 3,然后我看到了这个:

所以,请注意我是如何向 Repeater 提供 table(可能是 sql 查询,但在这种情况下,我们在代码中创建 table)。传递给转发器。

对于每个 table,itemdatabound 触发器。因为table有多个副本,所以我们需要使用find control.

如果您想 test/get 所有选中的项目,那么我们对 Repeater 项目中的每个项目执行一次 - 并再次使用查找控件来获取每个复选框控件。

但请注意我们只有两个复选框列表,但第二个在中继器内部,并且是数据驱动的。

因此,这将适用于 1 或“N”table秒。