Reputation: 663
I'm creating a custom datatype for Umbraco. This datatype simply reads records from a database and renders them in a html table, no repeaters. In each row there are, initially, two buttons, one to edit the record, and one to delete the record.
On clicking edit, the row is put into edit mode where textboxes are used in place of literals, and instead of buttons being "Edit" and "Delete", the are "Save" and "Cancel". Clicking either of these buttons does not seem to work. The command they should be firing is not firing.
I've read about having to create these buttons before page load, which i do. I have a List for each type (Save, Cancel). That is generated on Init, ids are based on the ids of the records. And the commands and command arguments are assigned here too.
However, the commands still do not seem to fire.
Code
public class ProductManagerDataEditor : System.Web.UI.UpdatePanel, umbraco.interfaces.IDataEditor
{
private umbraco.interfaces.IData _data;
//Properties
private List<Record> Records { get; set; }
private int EditRecordID = 0;
//Editor Controls
TextBox tb_EditName;
TextBox tb_EditPrice;
Button btn_Add;
List<Button> EditButtons;
List<Button> DeleteButtons;
List<Button> SaveButtons;
List<Button> CancelButtons;
/// <summary>
/// Constructor.
/// Reads in curent data along with configuration settings for this data type.
/// </summary>
/// <param name="Data"></param>
/// <param name="Configuration"></param>
public ProductManagerDataEditor(umbraco.interfaces.IData Data, SortedList<String, String> Configuration)
{
_data = Data;
}
public virtual bool TreatAsRichTextEditor
{
get { return false; }
}
public bool ShowLabel
{
get { return true; }
}
public Control Editor { get { return this; } }
public void Save()
{
}
/// <summary>
/// On Init Method
/// </summary>
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
/// <summary>
/// On Load Method
/// </summary>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
LoadRecords();
GenerateControls();
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
RenderTableContents(writer);
}
/// <summary>
/// Generates the buttons to be used
/// </summary>
protected void GenerateControls()
{
SaveButtons = new List<Button>();
CancelButtons = new List<Button>();
DeleteButtons = new List<Button>();
EditButtons = new List<Button>();
//Other Buttons
foreach (Record r in Records)
{
//Save Button
Button btn_Save = new Button();
btn_Save.CssClass = "btn-save";
btn_Save.ID = "btnSave_" + r.ID;
btn_Save.Text = "Save";
btn_Save.Command += new CommandEventHandler(Save);
btn_Save.CommandArgument = r.ID.ToString();
//Cancel Edting Button
Button btn_Cancel = new Button();
btn_Cancel.CssClass = "btn-cancel";
btn_Cancel.ID = "btnCancel";
btn_Cancel.Text = "Cancel";
btn_Cancel.Click += new EventHandler(CancelEdit);
//Delete Button
Button btn_Del = new Button();
btn_Del.CssClass = "btn-delete";
btn_Del.ID = "btnDelete_" + r.ID;
btn_Del.Text = "Delete";
btn_Del.Command += new CommandEventHandler(Delete);
btn_Del.CommandArgument = r.ID.ToString();
//Edit Button
Button btn_Edit = new Button();
btn_Edit.CssClass = "btn-edit";
btn_Edit.ID = "btnEdit_" + r.ID;
btn_Edit.Text = "Edit";
btn_Edit.Command += new CommandEventHandler(EditRecord);
btn_Edit.CommandArgument = r.ID.ToString();
SaveButtons.Add(btn_Save);
CancelButtons.Add(btn_Cancel);
DeleteButtons.Add(btn_Del);
EditButtons.Add(btn_Edit);
}
}
/// <summary>
/// Loads the records from the database
/// </summary>
protected void LoadRecords()
{
Records = //Loaded from db...
}
/// <summary>
/// Renders The Table of Records
/// </summary>
protected void RenderTableContents(HtmlTextWriter w)
{
bool editMode = false;
w.Write("<table class='product-manager' cellspacing='0' cellpadding='3px'>");
w.Write("<tr class='head'>");
w.Write("<th>Name</th>");
w.Write("<th>Price</th>");
w.Write("<th></th>");
w.Write("<th></th>");
w.Write("</tr>");
int buttonIndex = 0;
foreach (Record r in Records)
{
//If editing this record, display text boxes
if (EditRecordID == r.ID)
{
editMode = true;
tb_EditName = new TextBox { Text = r.Name };
tb_EditPrice = new TextBox { Text = r.Price.ToString() };
w.Write("<tr>");
w.Write("<td>");
tb_EditName.RenderControl(w);
w.Write("</td>");
w.Write("<td>");
tb_EditPrice.RenderControl(w);
w.Write("</td>");
w.Write("<td>");
SaveButtons[buttonIndex].RenderControl(w);
w.Write("</td>");
w.Write("<td>");
CancelButtons[buttonIndex].RenderControl(w);
w.Write("</td>");
w.Write("</tr>");
}
//Not in edit mode
else
{
w.Write("<tr>");
w.Write("<td>" + t.Name + "</td>");
w.Write("<td>£" + t.Price + "</td>");
w.Write("<td>");
EditButtons[buttonIndex].RenderControl(w);
w.Write("</td>");
w.Write("<td>");
DeleteButtons[buttonIndex].RenderControl(w);
w.Write("</td>");
w.Write("</tr>");
}
buttonIndex++;
}
w.Write("</table>");
}
#region Events
/// <summary>
/// Sets the id of the row to edit
/// </summary>
protected void EditRecord(object sender, CommandEventArgs e)
{
EditRecordID = e.CommandArgument.ToString();
}
/// <summary>
/// Cancels editing mode
/// </summary>
protected void CancelEdit(object sender, EventArgs e)
{
EditRecordID = 0;
}
/// <summary>
/// Deletes Selected Record
/// </summary>
protected void DeleteRecord(object sender, CommandEventArgs e)
{
//TODO
}
/// <summary>
/// Updates Record Details
/// </summary>
protected void Save(object sender, CommandEventArgs e)
{
//Update the Record
}
#endregion
}
Upvotes: 2
Views: 384
Reputation: 13286
I tried your code and apparently the problematic code was the rendering. The UpdatePanel
didn't treat the buttons as triggers at all.
The solution is to add the controls to the panel within an asp:Table
and let the UpdatePanel
do the rendering, so skip the rendering code.
This is what you need to change (this is just for the edit button but you can add code for all):
protected void GenerateControls()
{
var table = new Table();
var headerRow = new TableHeaderRow();
var headerCell = new TableHeaderCell();
headerCell.Text = "Name";
headerRow.Cells.Add(headerCell);
headerCell = new TableHeaderCell();
headerCell.Text = "Price";
headerRow.Cells.Add(headerCell);
headerCell = new TableHeaderCell();
headerRow.Cells.Add(headerCell);
headerCell = new TableHeaderCell();
headerRow.Cells.Add(headerCell);
table.Rows.Add(headerRow);
//Other Buttons
foreach (Record r in Records)
{
var row = new TableRow();
var cell = new TableCell();
//Edit Button
Button btn_Edit = new Button();
btn_Edit.CssClass = "btn-edit";
btn_Edit.ID = "btnEdit_" + r.ID;
btn_Edit.Text = "Edit";
btn_Edit.Command += new CommandEventHandler(EditRecord);
btn_Edit.CommandArgument = r.ID.ToString();
cell.Controls.Add(btn_Edit);
row.Cells.Add(cell);
table.Rows.Add(row);
}
ContentTemplateContainer.Controls.Add(table);
}
BTW, this looks like a grid. Why don't you use a GridView
or a ListView
?
Upvotes: 1