0

我正在尝试创建一个动态调查页面。这个想法看起来很简单,但是尝试在 ASP.NET 中实现它让我非常沮丧......

每个用户都链接到一个单独的(多项选择)问题列表。我有以下数据表:

调查:

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 在问题 y 上回答“总是”。)

这是我的第一个版本的代码:

<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 上进行 2 路数据绑定,我仍然完全一无所知?(我的意思是使用 <%# Bind() %> 命令。)或者我是否必须编写自己的程序来将答案提交回数据库?为了使事情变得更复杂,第一次访问时必须将答案插入到 Answers 表中,而在回访时,可以更新现有行。

4

1 回答 1

1

是的,当我想将 Bind 与 DropDownList 一起使用时,我发现了类似的问题。我所做的是从您的示例中创建一个自定义控件,该控件继承自 RadioButtonList。我给它一个额外的属性,称为值。设置好后,我会编写代码以通过值设置所选项目。当我调用 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>

安德鲁

于 2009-03-06T11:01:09.570 回答