2009-03-05 5 views
0

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

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

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 для ответа. (Таким образом, пользователь-х ответили "всегда" на вопрос-у.)

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

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

Однако я до сих пор полностью в темноте, если это возможно сделать 2-полосные привязки данных на RadioButtonLists? (Я имею в виду команду <% # Bind()%>). Или мне нужно написать собственную процедуру для отправки ответов обратно в базу данных? Чтобы усложнить ситуацию, при первом посещении ответы должны быть вставлены в таблицу «Ответы», а при возврате посещений существующие строки могут быть UPDATEd.

ответ

1

Да, я нашел аналогичную проблему, когда хочу использовать Bind с DropDownList. То, что я делаю, это создать пользовательский элемент управления из вашего примера, который наследуется от RadioButtonList. Я даю ему одно дополнительное свойство, называемое Value. Когда это установлено, я затем кодирую, чтобы установить выбранный элемент через значения. Когда я называю получай я вернуть фактическое значение выбранного таким образом, в сущности, вам нужен специальный класс, который наследуется от 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

+0

Попытка выяснить, как это использовать. Нужно ли компилировать как DLL и добавлять его в свой набор инструментов? – paulwhit