Let's say we want show some dynamic data on the web page, like notes. Notes will be represented by the NoteControl which will be a bunch of textboxes, labels and buttons:
<asp:TextBox ID="TitleTextBox" runat="server"></asp:TextBox>
<asp:TextBox ID="NoteTextTextBox" runat="server" TextMode="MultiLine"></asp:TextBox>
<asp:ImageButton
ID="AcceptNoteButton"
runat="server"
ImageUrl="~/Resources/Icons/64x64/circle-check.png"
AlternateText="Save"
CausesValidation="true" />
and will be rendered to something like that:
<input name="ctl00$MainContent$NotesView$ctl03$TitleTextBox" type="text" id="MainContent_NotesView_ctl03_TitleTextBox" />
<textarea name="ctl00$MainContent$NotesView$ctl03$NoteTextTextBox" id="MainContent_NotesView_ctl03_NoteTextTextBox" />
<input type="image" name="ctl00$MainContent$NotesView$ctl03$AcceptNoteButton" id="MainContent_NotesView_ctl03_AcceptNoteButton" data-objectid="57101f10-5aed-4285-99e7-2709c3ac41e9" src="../Resources/Icons/64x64/circle-check.png" alt="Save" />
protected void Page_Load(object sender, EventArgs e)
{
List<Note> notes = GetNotesFromDb();
RenderNotes(notes);
}
private void RenderNotes(List<Note> notes)
{
Panel notePanel = new Panel();
Notes.ContentTemplateContainer.Controls.Add(notePanel);
for (int i = 0; i < notes.Count; i++)
{
var note = notes[i];
// Here is our NoteControl
NoteControl noteCtrl = (NoteControl)Page.LoadControl("~/Controls/NoteControl.ascx");
noteCtrl.Note = note;
notePanel.Controls.Add(noteCtrl);
}
}
protected void acceptButton_Click(object sender, ImageClickEventArgs e)
{
var button = sender as ImageButton;
Guid id = Guid.Parse(button.Attributes[ObjectIdAttribute]);
UpdateNoteDb(id);
}
And because we attached this event handler in the markup:
<asp:ImageButton
ID="AcceptNoteButton"
runat="server"
ImageUrl="~/Resources/Icons/64x64/circle-check.png"
AlternateText="Save"
CausesValidation="true"
OnClick="acceptButton_Click" />
OK, let's say now we edited some note and now press the save button:
In a meanwhile, while we were editing this note, we opened the same page from the different machine and simply removed this note, and created a new one instead.
So when we hit the save button we get into Page_Load and... get all the notes from the database:
List<Note> notes = GetNotesFromDb();
And then we are rendering our page:
NoteControl noteCtrl = (NoteControl)Page.LoadControl("~/Controls/NoteControl.ascx");
...
notePanel.Controls.Add(noteCtrl);
<input name="ctl00$MainContent$NotesView$ctl03$TitleTextBox" type="text" value="Another one" id="MainContent_NotesView_ctl03_TitleTextBox"/>
<textarea name="ctl00$MainContent$NotesView$ctl03$NoteTextTextBox" id="MainContent_NotesView_ctl03_NoteTextTextBox">Indeed</textarea>
<input type="image" name="ctl00$MainContent$NotesView$ctl03$AcceptNoteButton" id="MainContent_NotesView_ctl03_AcceptNoteButton" data-objectid="78ae8c7f-7236-4a16-950d-b226f710485d" src="../Resources/Icons/64x64/circle-check.png" alt="Save" />
But before they will be rendered, all the events must fire... And *magically* we still handle the acceptButton_Click event. On the newly created control, which hasn't even been on the client yet.
Non-magically, data-objectid will be object id of the new note.
TitleTextBox.Text and NoteTextTextBox.Text will still get old values, because we set them only on initial page load:
if (!Page.IsPostBack)
{
TitleTextBox.Text = ...;
NoteTextTextBox.Text = ...;
}
Short story: we update the wrong object.
What can I say... You have to learn or you'll be the monkey which can code anything, if only the requirements are clear.


No comments:
Post a Comment