2012-11-07 94 views
0

我有以下嵌套的ListView ...OnCheckedChanged嵌套時,ListView控件

<asp:ListView ID="lvwRiskQuestions" runat="server" ItemPlaceholderID="QuestionItemPlaceholder"> 
    <LayoutTemplate> 
     <asp:PlaceHolder ID="QuestionItemPlaceholder" runat="server" /> 
    </LayoutTemplate> 
    <ItemTemplate> 
     <%# Eval("DESCRIPTION")%> 
      <asp:ListView ID="lvwAnswers" runat="server" ItemPlaceholderID="AnswerItemPlaceholder" DataSource='<%# Eval("Answers")%>'> 
       <LayoutTemplate> 
        <asp:PlaceHolder ID="AnswerItemPlaceholder" runat="server" /> 
       </LayoutTemplate> 
       <ItemTemplate> 
        <asp:RadioButton ID="rdbSelect" runat="server" AutoPostBack="true" OnCheckedChanged="rdbSelectChanged"/>           
         <%# Eval("Description")%> 
       </ItemTemplate> 
     </asp:ListView> 
    </ItemTemplate> 
</asp:ListView> 

我得到OnCheckedChanged像這樣的單選按鈕保持...

Protected Sub rdbSelectChanged(ByVal sender As Object, ByVal e As System.EventArgs) 

    Dim rb1 As RadioButton = CType(sender, RadioButton) 

    Dim lvwAnswers = DirectCast(lvwRiskQuestions.FindControl("lvwAnswers"), ListView) 

    For Each row As ListViewItem In lvwAnswers.Items 
     Dim rb As RadioButton = row.FindControl("rdbSelect") 
     If rb IsNot Nothing AndAlso rb.Checked Then 
      rb.Checked = False 
     End If 
    Next 
    rb1.Checked = True 
End Sub 

我的問題是「lvwAnswers ' 沒什麼。我猜我沒有正確地做我的findcontrol。

任何幫助非常感謝。

+0

是的,你沒有正確做你的FindControl。你的父母轉發器包含許多lvwAnswers。也許你可以嘗試像投射rb1.Parent.Parent(或rb1.BindingContainer.Parent)到ListView – jbl

回答

3

如果您只是爲答案生成單選按鈕列表,則可以使用RadioButtonList control。這將生成正確的HTML,因此每個問題只能選擇一個答案,而不必回退以取消選擇其他選項。

如果您的答案模板包含多個單獨的RadioButton,事情會變得更加複雜。當它不在RadioButtonList中時,RadioButton使用父NamingContainerUniqueID來構建其唯一的組名。遺憾的是,在您的示例中,NamingContainer將是lvwAnswers列表中的ListViewDataItem,並且每個答案都將具有不同的ID。

您需要的是一個RadioButton,它將查看NamingContainerNamingContainer以生成其組名。你既可以重新實施RadioButton控制,或使用反射的一點點更新私人_uniqueGroupName領域:

[ToolboxData("<{0}:ListRadioButton runat=\"server\" />")] 
public class ListRadioButton : RadioButton 
{ 
    private static readonly FieldInfo UniqueGroupNameField = FindUniqueGroupNameField(); 
    private string _uniqueGroupName; 

    private static FieldInfo FindUniqueGroupNameField() 
    { 
     return typeof(RadioButton).GetField("_uniqueGroupName", 
     BindingFlags.NonPublic | BindingFlags.Instance); 
    } 

    protected virtual string CreateUniqueGroupName() 
    { 
     string result = GroupName; 
     if (string.IsNullOrEmpty(result)) 
     { 
     result = ID; 
     } 
     if (string.IsNullOrEmpty(result)) 
     { 
     result = UniqueID; 
     } 
     else 
     { 
     Control container = NamingContainer; 
     if (container != null) 
     { 
      if (container is IDataItemContainer) 
      { 
       container = container.NamingContainer ?? container; 
      } 

      result = container.UniqueID + base.IdSeparator + result; 
     } 
     else 
     { 
      string uniqueID = UniqueID; 
      if (!string.IsNullOrEmpty(uniqueID)) 
      { 
       int index = uniqueID.LastIndexOf(base.IdSeparator); 
       if (index != -1) 
       { 
        result = uniqueID.Substring(0, 1 + index) + result; 
       } 
      } 
     } 
     } 

     return result; 
    } 

    private void EnsureUniqueGroupName() 
    { 
     if (_uniqueGroupName == null) 
     { 
     string value = CreateUniqueGroupName(); 
     if (UniqueGroupNameField != null) UniqueGroupNameField.SetValue(this, value); 
     _uniqueGroupName = value; 

     value = base.Attributes["value"]; 
     if (string.IsNullOrEmpty(value)) 
     { 
      base.Attributes["value"] = UniqueID; 
     } 
     } 
    } 

    protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection) 
    { 
     EnsureUniqueGroupName(); 
     return base.LoadPostData(postDataKey, postCollection); 
    } 

    protected override void Render(HtmlTextWriter writer) 
    { 
     EnsureUniqueGroupName(); 
     base.Render(writer); 
    } 
} 

隨着地方控制和使用site前綴,你可以改變你的代碼註冊:

<asp:ListView ID="lvwRiskQuestions" runat="server" ItemPlaceholderID="QuestionItemPlaceholder"> 
<LayoutTemplate> 
    <asp:PlaceHolder ID="QuestionItemPlaceholder" runat="server" /> 
</LayoutTemplate> 
<ItemTemplate> 
    <%# Eval("DESCRIPTION") %> 
    <asp:ListView ID="lvwAnswers" runat="server" ItemPlaceholderID="AnswerItemPlaceholder" DataSource='<%# Eval("Answers")%>'> 
    <LayoutTemplate> 
     <asp:PlaceHolder ID="AnswerItemPlaceholder" runat="server" /> 
    </LayoutTemplate> 
    <ItemTemplate> 
     <site:ListRadioButton ID="rdbSelect" runat="server" 
     Text='<%# Eval("Description") %>' 
     /> 
    </ItemTemplate> 
    </asp:ListView> 
</ItemTemplate> 
</asp:ListView> 

在渲染HTML中,單選按鈕,每題屆時將有相同的name,你只能選擇每個問題一個答案,而不必張貼在每個選擇整個頁面。

+0

這是一個很不錯的解決方案。可能是一個愚蠢的問題:爲什麼你不需要重寫LoadViewState和SaveViewState? – jbl

+0

因爲沒有其他東西需要保存在ViewState中。每個請求都會重新創建_uniqueGroupName字段。 –

-1

我想指出這個「複製/粘貼」代碼不起作用,並取自comment on codeproject(標題爲Another Option)。原始代碼確實有效。

這就是:

using System; 
using System.Collections.Specialized; 
using System.ComponentModel; 
using System.Reflection; 
using System.Security.Permissions; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

[AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] 
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] 
public class SimpleRadioButton : RadioButton 
{ 
    private static readonly FieldInfo UniqueGroupNameField = FindUniqueGroupNameField(); 
    private string _uniqueGroupName; 

    private static FieldInfo FindUniqueGroupNameField() 
    { 
     return typeof(RadioButton).GetField("_uniqueGroupName", 
      BindingFlags.NonPublic | BindingFlags.Instance); 
    } 

    protected virtual string CreateUniqueGroupName() 
    { 
     string result = this.GroupName; 
     if (string.IsNullOrEmpty(result)) 
     { 
      result = this.ID; 
     } 
     if (string.IsNullOrEmpty(result)) 
     { 
      result = this.UniqueID; 
     } 
     else 
     { 
      Control container = this.NamingContainer; 
      if (null != container) 
      { 
       if (container is IDataItemContainer) 
       { 
        container = container.NamingContainer ?? container; 
       } 

       result = container.UniqueID + base.IdSeparator + result; 
      } 
      else 
      { 
       string uniqueID = this.UniqueID; 
       if (!string.IsNullOrEmpty(uniqueID)) 
       { 
        int index = uniqueID.LastIndexOf(base.IdSeparator); 
        if (-1 != index) 
        { 
         result = uniqueID.Substring(0, 1 + index) + result; 
        } 
       } 
      } 
     } 

     return result; 
    } 

    private void EnsureUniqueGroupName() 
    { 
     if (null == _uniqueGroupName) 
     { 
      string value = this.CreateUniqueGroupName(); 
      if (null != UniqueGroupNameField) UniqueGroupNameField.SetValue(this, value); 
      _uniqueGroupName = value; 

      // Make sure we have a value attribute: 
      value = base.Attributes["value"]; 
      if (string.IsNullOrEmpty(value)) 
      { 
       base.Attributes["value"] = this.UniqueID; 
      } 
     } 
    } 

    protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection) 
    { 
     this.EnsureUniqueGroupName(); 
     return base.LoadPostData(postDataKey, postCollection); 
    } 

    protected override void Render(HtmlTextWriter writer) 
    { 
     this.EnsureUniqueGroupName(); 
     base.Render(writer); 
    } 
} 
+0

這不是「從對CodeProject的評論」;它基於我用來發布該評論的相同代碼! (在我的SO配置文件中查看我的「真實姓名」,並將其與我在CodeProject上的名稱進行比較。) –

+0

此外,我的答案中的代碼與我對CodeProject的評論完全相同(除了類名和一些小的外觀更改)。它適用於我,它適用於OP,所以我不知道爲什麼你認爲它不是? –

+0

我的歉意。我試圖確保這不是從其他人那裏「偷走」的。至於代碼「不工作」,它不適合我。但是我可能犯了一個錯誤,或者在動態控制中使用它。 – Mathlec