【问题标题】:Selected Items per listbox instead of all selected items in one listbox每个列表框的选定项目,而不是一个列表框中的所有选定项目
【发布时间】:2021-10-15 22:55:33
【问题描述】:

我的列表框选择了正确的值,但它分隔了每个列表框的值,而不是在一个列表框中插入所有值。

为什么会发生这种行为?

代码背后

protected void GvInBlocks_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                List<string> list = new List<string>();
                //Find listBoxCourse in GvChildBlock
                ListBox listBoxCourse = e.Row.FindControl("listBoxCourse") as ListBox;
                getCourseLB(listBoxCourse);

                //Fill control
                string CourseNames = (e.Row.FindControl("lblChildBlockCourse") as Label).Text;
                list.Add(CourseNames);

                foreach(ListItem items in listBoxCourse.Items)
                {
                    if(list.Contains(items.Value))
                    {
                        items.Selected = true;
                    }
                }


            }
        }

标记语言

<asp:Panel ID="pnlInBlocks" runat="server" Style="display: none">
<asp:GridView ID="GvInBlocks" runat="server" AutoGenerateColumns="false" CssClass="list" OnRowDataBound="GvInBlocks_RowDataBound">

<Columns>
<asp:TemplateField HeaderText = "Curso">
<ItemTemplate>
<asp:Label ID="lblChildBlockCourse" runat="server" Text='<%# Eval("CourseID") %>' Visible = "false" />
<asp:ListBox ID="listBoxCourse" runat="server" SelectionMode="Multiple">
</asp:ListBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>

</asp:GridView>
</asp:Panel>

编辑:

我编辑了代码,并用逗号分隔了值,但结果保持不变,是因为 RowDataBound 吗?如果数据库返回 2 行,它会返回 2 个列表框吗? 代码编辑:

//Find listBoxCourse in GvChildBlock
                ListBox listBoxCourse = e.Row.FindControl("listBoxCourse") as ListBox;
                getCourseLB(listBoxCourse);

                //Fill control
                string CourseNames = (e.Row.FindControl("lblChildBlockCourse") as Label).Text;
                string[] arrayNames = CourseNames.Split(',');

                foreach(var names in arrayNames)
                {
                    listBoxCourse.Items.FindByValue(names).Selected = true;
                }

【问题讨论】:

  • string CourseNames = (e.Row.FindControl("lblChildBlockCourse") as Label).Text; FindControl 看起来它正在返回您转换为字符串的多个项目,因此它正在创建字符串,每个返回的项目用逗号分隔。
  • 您必须将项目分开。查看 FindControl 返回的内容,您应该能够对它们执行 foreach 循环。自己做的时间不够。如果到时候其他人还没有回答,我可能稍后再看。
  • 该标签中的值/文本是如何分隔的?
  • 现在我检查了,标签内的值没有用任何逗号左右分隔
  • @OldDog 检查我在上面这篇文章中所做的编辑。

标签: c# asp.net listbox


【解决方案1】:

所以课程列表就像这样说:

Physics 204, Math 220, Computing 220

那么,你需要将上面的列表框拆分成一个“列表”

例如: //填充控件

 string CourseNames = (e.Row.FindControl("lblChildBlockCourse") as Label).Text;
 CourseNames = CourseNames.Repace(", ",","); ' remove blanks

 List<string> slCourse = (List<string>)CourseNames.Split(',').ToList();
 listBoxCourse.DataSource = slCourse;
 listBoxCourse.DataBind();

现在,您的列表框已填满值。

或者是否有一个 100% 单独的选项列表应该驱动列表框,而您只想选择/设置一个课程名称作为列表框中的选定值?

好的,对于一些非常奇怪的设计,我们应该有这样的设置:

你有一些学生,他们正在学习的课程表,第三张表实际上只是所有课程的列表。

但是,出于某种奇怪的原因,我们没有课程表,并且有这个:

更糟糕的是,我们有一些方法有“一个”列,其中包含学生正在使用的“id”列表(同样,违反了所有规则 - 使得任何类型的解决方案都非常困难)。

甚至更糟?所需的输出是显示每一行的所有课程,并且只突出显示学生注册的课程。

在我看来,每一行应该只显示他们的课程,而不是全部,然后在该列表中显示突出显示的课程。

但是,让我们继续这个“非常奇怪的另一个星球的问题,这样做没有意义。

所以,我们必须填满网格,(简单)。我们还必须放入所有课程的列表框。

所以,让我们先做这部分,然后我们处理高亮部分。

所以,我们有这个网格 - 几列和列表框

    <div style="width:40%;padding:35px">

        <asp:GridView ID="GVStudents" runat="server" CssClass="table" AutoGenerateColumns="False"
            DataKeyNames="ID" OnRowDataBound="GVStudents_RowDataBound" >
            <Columns>
                <asp:BoundField DataField="FirstName"    HeaderText="FirstName"  />
                <asp:BoundField DataField="LastName"     HeaderText="LastName"  />
                <asp:BoundField DataField="CourseIDList" HeaderText="CourseIDList" />

                <asp:TemplateField HeaderText="Courses" HeaderStyle-Width="190px">
                    <ItemTemplate>
                        <asp:ListBox ID="LstCourses" runat="server" Style="Height:120px;width:170px"
                            DataValueField ="ID"
                            DataTextField ="Course">
                        </asp:ListBox>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </div>

好的,现在代码来填写:

public partial class StudentListBox1 : System.Web.UI.Page
{
    DataTable rstCourses = new DataTable();
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadGrid();

    }

    void LoadGrid()
    {
        rstCourses = MyRst("SELECT ID, Course from Courses ORDER BY Course");
        // load grid
        GVStudents.DataSource = MyRst("SELECT * FROM Students Order by FirstName");
        GVStudents.DataBind();
    }

    protected void GVStudents_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        // for each row, load up listbox with courses
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            ListBox lv = (ListBox)e.Row.FindControl("LstCourses");
            lv.DataSource = rstCourses;
            lv.DataBind();
        }
    }

    public DataTable MyRst(string strSQL)
    {
        DataTable rstData = new DataTable();
        using (SqlConnection con = new SqlConnection(Properties.Settings.Default.TEST4))
        using (SqlCommand cmdSQL = new SqlCommand(strSQL, con))
        {
            con.Open();
            rstData.Load(cmdSQL.ExecuteReader());
        }
        return rstData;
    }

现在输出是这样的:

因此,下一段代码是从该列中获取该 id 列表,并突出显示课程列表框中的课程。 (如果可行,那么我们可以删除该网格中的“id 列表”行。因此,让我们编写该部分以突出显示课程。

代码将/可能是:

(我们在填充列表框的数据绑定代码之后添加。

所以我们现在从上面得到了这个:

    protected void GVStudents_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        // for each row, load up listbox with courses
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            ListBox lv = (ListBox)e.Row.FindControl("LstCourses");
            lv.DataSource = rstCourses;
            lv.DataBind();

            // get "item list" column (we NOT use from grid, since we plan to remove
            // from grid display - so, get this from the data source
            DataRowView gData = (DataRowView)e.Row.DataItem;

            List<string> sIdList = gData["CourseIDList"].ToString().Split(' ').ToList();

            foreach (ListItem lBox in lv.Items)
            {
                lBox.Selected = sIdList.Contains(lBox.Value);
            } 
        }
    }

现在我们有了这个输出:

现在,在我看来,最好只在每个列表框中显示他们拥有的课程。

另一方面,我想我们可以开始使用上述方法来勾选(为每个用户选择更多课程)。我们可以使用上面的网格。

编辑 ========================================= ===

好的,所以我们现在有了更多信息,并且每一行都没有作为“id”的课程列表,由一些分隔符分隔。

所以,我们可以转储 id 列表列表列,现在只有一行中的学生信息 + 一个课程列表框,如下所示:

  <asp:GridView ID="GVStudents" runat="server" CssClass="table" AutoGenerateColumns="False"
        DataKeyNames="ID" OnRowDataBound="GVStudents_RowDataBound" >
        <Columns>
            <asp:BoundField DataField="FirstName"    HeaderText="FirstName"  />
            <asp:BoundField DataField="LastName"     HeaderText="LastName"  />

            <asp:TemplateField HeaderText="Courses" HeaderStyle-Width="190px">
                <ItemTemplate>
                    <asp:ListBox ID="LstCourses" runat="server" Style="Height:120px;width:170px"
                        DataValueField ="ID"
                        DataTextField ="Course"
                        SelectionMode="Multiple"
                        SelectMethod="">
                    </asp:ListBox>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

现在我们填写列表框的代码变成了这样:

   protected void GVStudents_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        // for each row, load up listbox with courses
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            ListBox lv = (ListBox)e.Row.FindControl("LstCourses");
            lv.DataSource = rstCourses;
            lv.DataBind();

            // now get all courses for this student

            DataRowView gData = (DataRowView)e.Row.DataItem;

            int StudentPK = (int)gData["ID"];
            
            DataTable rstStudentCourses;
            string strSQL = "SELECT Course_ID FROM StudentCourses WHERE Student_ID = " + StudentPK;
            rstStudentCourses = MyRst(strSQL);
           
            foreach (ListItem lBox in lv.Items)
            {
                string sFind = "Course_ID = " + lBox.Value;
                lBox.Selected = (rstStudentCourses.Select(sFind).Count() > 0);
            } 
        }

输出是这样的:

如前所述,每行最好只显示所学的课程,而不是突出显示所有可能的课程。

当然这是一个简单的改变,我们会 DUMP 全局范围的课程数据表,并为每一行简单拉出课程列表,并直接用这些课程填充列表框(代码会更少,因为没有匹配循环现在需要针对列表框中的整个课程列表。(但只需查询以仅用一行/学生的课程填充列表框)。

【讨论】:

  • 可变课程名称只是 ID,但这些 ID 没有逗号分隔。列表框的选定值可以是多个值,这些值来自一个数据库。
  • 在帖子中检查我上面的编辑。
  • 你有时间去看看吗? @Albert D. Kallal?
  • 当然,看看我的编辑。我展示了如何在网格中有一个列表框,然后如何将每个“id”选择到列表框中。我有点想,最好只在列表框中显示他们有哪些课程,而不是突出显示他们有哪些课程,但无论如何 - 请参阅我的编辑以及它是如何工作的。
  • 好的,几乎所有的,但我不能像你在“CourseIDList”列中那样做你是如何设法将所有的ID插入一行的?我的网格正在为每个“CourseIDList”创建一行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-28
  • 2023-04-01
相关资源
最近更新 更多