2

I am trying to populate a Nested Repeater by databinding it to a Generic List.

The user will be able to add / remove values from this Generic List at will.
All this is neatly wrapped in an Ajax Update Panel.

I am now having a problem that when the user tries to add values to the Generic List, it only adds ` initial value, then keeps updating that value when they click to add more.

I have a suspicion that its because the Generic List doesn't keel its initial data or something; but I'm really not too sure.

Please can someone help.

Chalenge.cs

public class challenge
{
    public class Team
    {
        public string TeamName { get; set; } 
    }
    public class Member:Team
    {
        public string Name { get; set; }
    }

    //This is just a test, but I cant get a list in a class file to work properly.
    public class ChallengeList
    {
        public List<Member> Member()
        {
            return null;
        }
    }
}

Page.cs

private List<challenge.Member> Members = new List<challenge.Member>();

protected void Page_Load(object sender, EventArgs e)
{
    if (Page.IsPostBack) return;

    lblCurrent.Text = SiteSession.Current.Nickname;
    lblChallenge.Text = Request.QueryString["Challenge"];

    //Add the initial teams
    PopulateTeamRepeater();
    AddData();
}

private List<challenge.Member> AddData()
{
    Members.Add(
        new challenge.Member
            {
                Name = SiteSession.Current.Nickname,
                TeamName = "Team One"
            });
    Members.Add(
            new challenge.Member
                {
                    Name = Request.QueryString["Challenge"],
                    TeamName = "Team Two"
                });

    return Members;
}

/// <summary>
/// Add the selected member to the team
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void drpTeams_SelectedIndexChanged(object sender, EventArgs e)
{
    Members.Add(
        new challenge.Member
        {
            Name = tbMemberAuto.Text,
            TeamName = drpTeams.SelectedItem.Value
        });


    PopulateTeamRepeater();
}

UPDATE: Binding of the repeaters (Same page)

 /// <summary>
    /// Populates the Team repeater control with the amount of teams the user has selected
    /// </summary>
    private void PopulateTeamRepeater()
    {


        ArrayList cArrayList = new ArrayList(); //Main holder
        StringBuilder sb = new StringBuilder(); //Temp holer

        try
        {

            //Get all team numbers
            foreach (challenge.Member Team in AddData())
            {
                //Add it to the string builder
                sb.Append(Team.TeamName + ";");
            }

            //Split the string to get the strings (As a temporary holder)
            string[] cs = sb.ToString().Split(';');

            //Add the groups (unique) to the next holder
            foreach (string s in cs.Where(s => !cArrayList.Contains(s)))
            {
                cArrayList.Add(s);
            }

            rptTeam.DataSource = cArrayList;
            rptTeam.DataBind();
        }
        catch (Exception es)
        {
            misc.ChangeInfo(Master.Page, "Error filling teams: " + es.Message, "ui-state-error");
        }
    }

/// <summary>
/// Populate the Member repeater based on the Team
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void rptTeam_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    Repeater rptMembers = (Repeater)e.Item.FindControl("rptMembers");
    Label lblTeam = (Label)e.Item.FindControl("lblTeam");

    rptMembers.DataSource = AddData().Where(m => m.TeamName == lblTeam.Text);
    rptMembers.DataBind();
}
TheGeekZn
  • 3,696
  • 10
  • 55
  • 91
  • To the rest (After applying the below answer): remove `private List AddData()`, and replace all references in the code with `Members` – TheGeekZn Nov 01 '12 at 07:12

1 Answers1

2

You can keep them on view state as:

const string cChalMemNameConst = "ChalMem_cnst";

public List<challenge.Member> Members
{
    get
    {
        if (!(ViewState[cChalMemNameConst] is List<challenge.Member>))
        {
            // need to fix the memory and added to viewstate
            ViewState[cChalMemNameConst] = new List<challenge.Member>();
        }

        return (List<challenge.Member>)ViewState[cChalMemNameConst];
    }
}

Also add the [Serializable] attributes on your class that you place on the List<> as:

[Serializable]
public class challenge
{
    [Serializable]
    public class Team
    {
        public string TeamName { get; set; } 
    }

    [Serializable]
    public class Member:Team
    {
        public string Name { get; set; }
    }

    [Serializable]
    public class ChallengeList
    {
        public List<Member> Member()
        {
            return null;
        }
    }
}

note: The line private List<challenge.Member> Members = new List<challenge.Member>(); must be change by the above statement of save it to viewstate.

Aristos
  • 66,005
  • 16
  • 114
  • 150
  • \:D/... But... What exactly is `cArrNameConst` – TheGeekZn Nov 01 '12 at 06:50
  • @NewAmbition Just a way to place the same string on 3 place with out making error. Ah, sorry I make a type error (bug), I fix it. Copy paste this code and tell me if its works :) – Aristos Nov 01 '12 at 06:51
  • Seems to be working perfectly, except I am getting multiple bindings of the same value. Updating my code to show you how im binding the repeaters – TheGeekZn Nov 01 '12 at 06:57
  • @NewAmbition I do not know what control you bind with that values. You have two options. 1. is to disable the viewstate for that control so not keep the values both on class and on control, 2. is to clear the list on control before you set the values again. – Aristos Nov 01 '12 at 07:02
  • 1
    This answer works perfectly, thank you @Aristos :D You are amazing! (PS: was by my own ignorance that i accidently added more than what was required to the repeater). – TheGeekZn Nov 01 '12 at 07:11