Могу ли я связать данные (2-way) динамически генерируемые списки RadioButtonLists? - PullRequest
0 голосов
/ 05 марта 2009

Я пытаюсь создать динамическую страницу опроса. Идея кажется простой, но попытки реализовать ее в ASP.NET меня очень расстраивают ...

Каждый пользователь связан с отдельным списком вопросов с несколькими вариантами ответов. У меня есть следующие таблицы данных:

Surveys:

User   | Question   | Rank
-------+------------+-----
user-x | question-x |    1
user-x | question-y |    2
user-y | question-z |    1
user-y | question-x |    2

Вопросы:

ID         | Text | Choices
-----------+------+-----------------------
question-x | Foo? | yes|no
question-y | Bar? | never|sometimes|always
question-z | Baz? | 1|2|3|4|5|6|7|8|9|10

Ответы:

User   | Question   | Answer
-------+------------+-------
user-x | question-x |    0
user-x | question-y |    2
user-y | question-z |    5

Таким образом, варианты ответа - это разделенные символами строки, которые необходимо использовать при привязке данных, а ответы сохраняются в виде индекса на основе 0 для ответа. (Таким образом, пользователь-x ответил «всегда» на вопрос-у.)

Вот моя первая версия кода:

<asp:SqlDataSource ID="SqlDataSource1" runat="server" 
    ConnectionString="<%$ ConnectionStrings:dbconn %>" 
    SelectCommand="
        SELECT Questions.Text AS Question, Questions.Choices, Answers.Answer 
        FROM Questions 
            INNER JOIN Surveys ON Surveys.Question = Questions.ID 
            LEFT OUTER JOIN Answers ON Questions.ID = Answers.Question 
                AND Users.ID = Answers.User 
        WHERE (Surveys.User = @User) 
        ORDER BY Surveys.Rank">
    <SelectParameters>
        <asp:QueryStringParameter Name="User" QueryStringField="id" />
    </SelectParameters>
</asp:SqlDataSource>

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1" 
    onitemdatabound="Repeater1_ItemDataBound">
    <HeaderTemplate><table></HeaderTemplate>
    <ItemTemplate>
        <tr>
            <td><%# Eval("Question") %></td>
            <td><asp:Label runat="server" ID="ChoicesLabel"/></td>
        </tr>
    </ItemTemplate>
    <FooterTemplate></table></FooterTemplate>
</asp:Repeater>

<asp:Button ID="Button1" runat="server" Text="Submit" onclick="Button1_Click"/>

и

protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem) 
        return;

    DataRowView row = (DataRowView)e.Item.DataItem;
    RadioButtonList rbl = new RadioButtonList();
    rbl.RepeatDirection = RepeatDirection.Horizontal;
    string[] Choices = row["Choices"].ToString().Split('|');
    for (int n = 0; n < Choices.Length; n++)
    {
        rbl.Items.Add(new ListItem(Choices[n], n.ToString()));
    }
    if (row["Answer"] != DBNull.Value)
        rbl.SelectedIndex = (int)row["Answer"];
    ((Label)e.Item.FindControl("ChoicesLabel")).Controls.Add(rbl);
}

protected void Button1_Click(object sender, EventArgs e)
{
}

Теперь первая проблема заключалась в том, что после нажатия кнопки «Отправить» я получаю взамен страницу, на которой только содержит вопросы, а не радиокнопки с ответами! После долгих поисков я исправил это, заставив привязку данных происходить при инициализации страницы:

public void Page_Init(Object sender, EventArgs e)
{
    Repeater1.DataBind();
}

Тем не менее, я все еще в полном неведении, если возможно сделать двухстороннее связывание данных в списках RadioButtonLists? (Я имею в виду с помощью команды <% # Bind ()%>.) Или я должен написать свою собственную процедуру для отправки ответов обратно в базу данных? Чтобы усложнить задачу, при первом посещении ответы должны быть вставлены в таблицу ответов, а при повторных посещениях существующие строки могут быть ОБНОВЛЕНЫ.

1 Ответ

1 голос
/ 06 марта 2009

Да, я обнаружил похожую проблему, когда хочу использовать Bind с DropDownList. Что я делаю, это создаю пользовательский элемент управления из вашего примера, который наследуется от RadioButtonList. Я даю ему одно дополнительное свойство под названием Value. Когда это установлено, я затем код для установки выбранного элемента через значения. Когда я вызываю get, я возвращаю фактическое выбранное значение, так что по сути вам нужен пользовательский класс, который наследуется от RadioButtonList и присваивает ему дополнительное свойство

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;

/// <summary>
/// Summary description for BindingRadioButtonList
/// </summary>
public class BindingRadioButtonList : RadioButtonList
{
    public string Value
    {
        get
        {
            return this.SelectedValue;
        }
        set
        {
            if (this.Items.FindByValue(value) != null)
            {
                this.ClearSelection();
                this.Items.FindByValue(value).Selected = true;
            }
        }
    }

    public BindingRadioButtonList()
    {
        //
        // TODO: Add constructor logic here
        //
    }
}

Я могу легко использовать это:

<cc1:BindingRadioButtonList ID="a1" runat="server" Value='<%#Bind("YourValue")%>'>
</cc1:BindingRadioButtonList>

Andrew

...