Выбранные элементы в списке вместо всех выбранных элементов в одном списке

#c# #asp.net #listbox

Вопрос:

Мой список правильно выбирает значения, но он разделяет значения по списку, а не вставляет все значения в одно поле списка.

Почему происходит такое поведение?

Код За

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

Комментарии:

1. строковые имена курсов = (например, Строка.FindControl(«lblChildBlockCourse») в качестве метки). Текст; FindControl выглядит так, как будто он возвращает несколько элементов, которые вы преобразуете в строку, поэтому он создает строку с каждым возвращенным элементом, разделенным запятыми.

2. Вы должны разделить предметы. Посмотрите, что возвращает FindControl, и вы сможете выполнить цикл foreach для них. Не хватает времени, чтобы сделать это самому. Я, наверное, смогу посмотреть его позже, если к тому времени кто-нибудь еще не ответит.

3. как-то разделены значения/текст в этой метке?

4. Теперь , когда я проверил, значения внутри метки не разделены запятыми или около того

5. @OldDog Проверьте правку, которую я сделал в этом посте выше.

Ответ №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% отдельный список вариантов, которые должны управлять полем «Список», и вы хотите выбрать/задать только ОДНО имя курса в качестве выбранного значения в поле «Список»?

Хорошо, для какого-то ОЧЕНЬ странного дизайна нам следует настроить эту настройку:

введите описание изображения здесь

У вас есть несколько студентов, таблица курсов, которые они проходят, и 3-я таблица-это на самом деле просто список всех курсов.

но по какой-то странной причине у нас нет таблицы курсов, и у нас есть это:

введите описание изображения здесь

Хуже того, у нас есть «одна» колонка, в которой есть список «идентификаторов», которые принимает студент (опять же, нарушает все правила — делает ЛЮБОЕ решение очень сложным).

И что еще хуже? Желаемый результат-отобразить ВСЕ курсы для каждой строки и выделить ТОЛЬКО тот, на который зачислен студент.

Мне кажется, что в каждой строке должны отображаться ТОЛЬКО их курсы, а не все, а затем в этом списке показать выделенные.

Но, давайте покончим с этим «ОЧЕНЬ странным вопросом с другой планеты, в котором нет смысла делать это таким образом.

Итак, мы должны заполнить сетку (легко). Мы также должны указать в списке ВСЕ КУРСЫ.

Итак, давайте сначала выполним эту часть, а ЗАТЕМ поработаем над основной частью.

Итак, у нас есть эта сетка — несколько столбцов и поле со списком

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

И теперь на выходе получается вот это:

введите описание изображения здесь

Поэтому следующим фрагментом кода было бы взять этот список идентификаторов из этого столбца и осветить курсы в списке курсов. (и если это сработает, то мы можем удалить строку «список идентификаторов» в этой сетке. Итак, давайте напишем эту часть, чтобы выделить курсы.

Код будет/может быть:

(мы добавляем сразу после кода привязки данных, который заполнил поле списка.

Так что теперь у нас сверху есть это:

     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);
            } 
        }
    }
 

И теперь у нас есть этот результат:

введите описание изображения здесь

Теперь, мне кажется, было бы лучше показать ТОЛЬКО те курсы, которые у них есть в каждом списке.

С другой стороны, я полагаю, что мы могли бы начать использовать вышесказанное для галочки (выберите больше курсов для каждого пользователя). И мы могли бы использовать для этого вышеприведенную сетку.

Править ===========================================

Итак, теперь у нас есть дополнительная информация и что в каждой строке НЕТ списка курсов в качестве «идентификатора», разделенного некоторыми разделителями.

итак, мы можем сбросить столбец списка идентификаторов, и теперь у нас есть только информация о студентах в одной строке поле со списком курсов, подобных этому:

   <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);
            } 
        }
 

И выход такой:

введите описание изображения здесь

Как уже отмечалось, возможно, было бы лучше, чтобы в каждой строке отображались ТОЛЬКО пройденные курсы, а не просто выделялись из ВСЕХ возможных курсов.

Конечно, это простое изменение, и мы бы СБРОСИЛИ данные курсов с глобальной областью действия и просто извлекли список курсов для каждой строки и непосредственно заполнили поле списка этими курсами (это было бы меньше кода, так как теперь не требовалось бы никакого цикла сопоставления со всем списком курсов в поле списка. (но просто запросите, чтобы заполнить список ТОЛЬКО курсами для одной строки/студента).

Комментарии:

1. Имена переменных курсов-это просто идентификаторы , но у этих идентификаторов нет запятой, чтобы разделить их. Выбранные значения в списке могут быть несколькими значениями , эти значения берутся из базы данных.

2. Проверьте мою правку выше в посте.

3. У вас было время, чтобы проверить это? @Альберт Д. Каллал?

4. Конечно, взгляните на мою правку. Я показываю, как создать поле со списком в сетке, а затем, как добавить каждый «идентификатор» в поле со списком. Я вроде как думаю, что было бы лучше просто показать, какие курсы у них есть в списке, вместо того, чтобы выделять, какие у них есть, но независимо от этого — смотрите мое редактирование и как это работает.

5. Хорошо , получил почти все, но я не могу сделать это так, как вы сделали в столбце «Список идентификаторов курса», как вам удалось вставить все идентификаторы в одну строку? Моя сетка создает строку для каждого «списка курсов».