У меня есть класс BaseTemplate
public abstract class BaseTemplate : ITemplate
Это добавляет элементы управления и предоставляет абстрактные методы для реализации в наследующем классе. Затем наследующий класс добавляет свой HTML в соответствии с источником данных и управляет связыванием данных.
Это все работает нормально - у меня появляется элемент управления с правильно проанализированным html.
Проблема в том, что базовый класс добавляет в шаблон элементы управления, которые имеют свои собственные аргументы CommandName; идея заключается в том, что класс, реализующий пользовательский шаблонный список данных, будет обеспечивать логику установки выбранных и редактируемых индексов. Этот класс также управляет связыванием данных и т. Д. Он устанавливает все шаблоны в списке данных в методе Init (что было еще одной причиной этого исключения).
Исключение выдается, когда я нажимаю одну из этих кнопок - я пытался подключить их события щелчка и команды везде на случай, если это было проблемой. Я также гарантировал, что их имена команд не совпадают ни с одним из системных имен. Трассировка стека не содержит ссылок на мои методы или объекты, поэтому я так застрял. Это самое бесполезное сообщение, которое я могу себе представить.
Действительно расстраивает то, что я не могу заставить точку останова сработать - то есть проблема возникает после того, как я нажимаю кнопку, но до и моего кода может выполняться.
В последний раз это исключение происходило, когда я имел этот код в пользовательском элементе управления и назначал шаблоны для списка данных в PageLoad. Я переместил их в init, чтобы решить эту проблему; тем не менее, это была проблема, которая существовала тогда, и я понятия не имею, что вызывает ее, не говоря уже о том, как ее решить (а индекс вне диапазона на самом деле не помогает, не зная, какой индекс).
Сведения об исключении
Exception Details: System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: index
Трассировка стека:
[ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: index]
System.Web.UI.ControlCollection.get_Item(Int32 index) +8665582
System.Web.UI.WebControls.DataList.GetItem(ListItemType itemType, Int32 repeatIndex) +8667655
System.Web.UI.WebControls.DataList.System.Web.UI.WebControls.IRepeatInfoUser.GetItemStyle(ListItemType itemType, Int32 repeatIndex) +11
System.Web.UI.WebControls.RepeatInfo.RenderVerticalRepeater(HtmlTextWriter writer, IRepeatInfoUser user, Style controlStyle, WebControl baseControl) +8640873
System.Web.UI.WebControls.RepeatInfo.RenderRepeater(HtmlTextWriter writer, IRepeatInfoUser user, Style controlStyle, WebControl baseControl) +27
System.Web.UI.WebControls.DataList.RenderContents(HtmlTextWriter writer) +208
System.Web.UI.WebControls.BaseDataList.Render(HtmlTextWriter writer) +30
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer) +163
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +32
System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter output) +51
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
System.Web.UI.HtmlControls.HtmlForm.RenderControl(HtmlTextWriter writer) +40
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
System.Web.UI.Page.Render(HtmlTextWriter writer) +29
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1266
код
Базовый класс:
public abstract class BaseTemplate : ITemplate
{
ListItemType _templateType;
public BaseTemplate(ListItemType theTemplateType)
{ _templateType = theTemplateType; }
public ListItemType ListItemType
{ get { return _templateType; } }
#region ITemplate Members
public void InstantiateIn(Control container)
{
PlaceHolder ph = new PlaceHolder();
container.Controls.Add(ph);
Literal l = new Literal();
switch (_templateType)
{
case ListItemType.Header:
{
ph.Controls.Add(new LiteralControl(@"<table><tr>"));
InstantiateInHeader(ph);
ph.Controls.Add(new LiteralControl(@"</tr>"));
break;
}
case ListItemType.Footer:
{
ph.Controls.Add(new LiteralControl(@"<tr>"));
InstantiateInFooter(ph);
ph.Controls.Add(new LiteralControl(@"</tr></table>"));
break;
}
case ListItemType.Item:
{
ph.Controls.Add(new LiteralControl(@"<tr>"));
InstantiateInItem(ph);
ph.Controls.Add(new LiteralControl(@"<td>"));
Button select = new Button();
select.ID = "btnSelect";
select.CommandName = "SelectRow";
select.Text = "Select";
ph.Controls.Add(select);
ph.Controls.Add(new LiteralControl(@"</td>"));
ph.Controls.Add(new LiteralControl(@"</tr>"));
ph.DataBinding += new EventHandler(ph_DataBinding);
break;
}
case ListItemType.AlternatingItem:
{
ph.Controls.Add(new LiteralControl(@"<tr>"));
InstantiateInAlternatingItem(ph);
ph.Controls.Add(new LiteralControl(@"<td>"));
Button select = new Button();
select.ID = "btnSelect";
select.CommandName = "SelectRow";
select.Text = "Select";
ph.Controls.Add(select);
ph.Controls.Add(new LiteralControl(@"</td>"));
ph.Controls.Add(new LiteralControl(@"</tr>"));
ph.DataBinding+=new EventHandler(ph_DataBinding);
break;
}
case ListItemType.SelectedItem:
{
ph.Controls.Add(new LiteralControl(@"<tr>"));
InstantiateInItem(ph);
ph.Controls.Add(new LiteralControl(@"<td>"));
Button edit = new Button();
edit.ID = "btnEdit";
edit.CommandName = "EditRow";
edit.Text = "Edit";
ph.Controls.Add(edit);
Button delete = new Button();
delete.ID = "btnDelete";
delete.CommandName = "DeleteRow";
delete.Text = "Delete";
ph.Controls.Add(delete);
ph.Controls.Add(new LiteralControl(@"</td>"));
ph.Controls.Add(new LiteralControl(@"</tr>"));
ph.DataBinding += new EventHandler(ph_DataBinding);
break;
}
case ListItemType.EditItem:
{
ph.Controls.Add(new LiteralControl(@"<tr>"));
InstantiateInEdit(ph);
ph.Controls.Add(new LiteralControl(@"<td>"));
Button save = new Button();
save.ID = "btnSave";
save.CommandName = "SaveRow";
save.Text = "Save";
ph.Controls.Add(save);
Button cancel = new Button();
cancel.ID = "btnCancel";
cancel.CommandName = "CancelRow";
cancel.Text = "Cancel";
ph.Controls.Add(cancel);
ph.Controls.Add(new LiteralControl(@"</td>"));
ph.Controls.Add(new LiteralControl(@"</tr>"));
ph.DataBinding += new EventHandler(ph_DataBinding);
break;
}
case ListItemType.Separator:
{
InstantiateInSeperator(ph);
break;
}
}
}
void ph_DataBinding(object sender, EventArgs e)
{
DataBindingOverride(sender, e);
}
/// <summary>
/// the controls placed into the PlaceHolder will get wrapped in <table><tr> </tr>. I.e. you need to provide the column names wrapped in <td></td> tags.
/// </summary>
/// <param name="header"></param>
public abstract void InstantiateInHeader(PlaceHolder ph);
/// <summary>
/// the controls will have a column added after them and so require each column to be properly wrapped in <td></td> tags. The <tr></tr> is handled in the base class.
/// </summary>
/// <param name="ph"></param>
public abstract void InstantiateInItem(PlaceHolder ph);
/// <summary>
/// the controls will have a column added after them and so require each column to be properly wrapped in <td></td> tags. The <tr></tr> is handled in the base class.
/// </summary>
/// <param name="ph"></param>
public abstract void InstantiateInAlternatingItem(PlaceHolder ph);
/// <summary>
/// the controls will have a column added after them and so require each column to be properly wrapped in <td></td> tags. The <tr></tr> is handled in the base class.
/// </summary>
/// <param name="ph"></param>
public abstract void InstantiateInEdit(PlaceHolder ph);
/// <summary>
/// Any html used in the footer will have </tr><table> appended to the end.
/// <tr> will be appended to the front.
/// </summary>
/// <param name="ph"></param>
public abstract void InstantiateInFooter(PlaceHolder ph);
/// <summary>
/// the controls will have a column added after them and so require each column to be properly wrapped in <td></td> tags. The <tr></tr> is handled in the base class.
/// Adds Delete and Edit Buttons after the table contents.
/// </summary>
/// <param name="ph"></param>
public abstract void InstantiateInSelectedItem(PlaceHolder ph);
/// <summary>
/// The base class provides no <tr></tr> tags
/// </summary>
/// <param name="ph"></param>
public abstract void InstantiateInSeperator(PlaceHolder ph);
/// <summary>
/// Use this method to bind the controls to their data.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public abstract void DataBindingOverride(object sender, EventArgs e);
#endregion
}
Класс наследования:
public class NominalGroupTemplate : BaseTemplate
{
public NominalGroupTemplate(ListItemType theListItemType)
: base(theListItemType) { }
public override void InstantiateInHeader(PlaceHolder ph)
{
ph.Controls.Add(new LiteralControl(@"<td>ID</td><td>Group</td><td>IsPositive</td>"));
}
public override void InstantiateInItem(PlaceHolder ph)
{
ph.Controls.Add(new LiteralControl(@"<td>"));
Label lblID = new Label();
lblID.ID = "lblID";
ph.Controls.Add(lblID);
ph.Controls.Add(new LiteralControl(@"</td><td>"));
Label lblGroup = new Label();
lblGroup.ID = "lblGroup";
ph.Controls.Add(lblGroup);
ph.Controls.Add(new LiteralControl(@"</td><td>"));
CheckBox chkIsPositive = new CheckBox();
chkIsPositive.ID = "chkIsPositive";
chkIsPositive.Enabled = false;
ph.Controls.Add(chkIsPositive);
ph.Controls.Add(new LiteralControl(@"</td>"));
}
public override void InstantiateInAlternatingItem(PlaceHolder ph)
{
InstantiateInItem(ph);
}
public override void InstantiateInEdit(PlaceHolder ph)
{
ph.Controls.Add(new LiteralControl(@"<td>"));
Label lblID = new Label();
lblID.ID = "lblID";
ph.Controls.Add(lblID);
ph.Controls.Add(new LiteralControl(@"</td><td>"));
TextBox txtGroup = new TextBox();
txtGroup.ID = "txtGroup";
txtGroup.Visible = true;
txtGroup.Enabled = true ;
ph.Controls.Add(txtGroup);
ph.Controls.Add(new LiteralControl(@"</td><td>"));
CheckBox chkIsPositive = new CheckBox();
chkIsPositive.ID = "chkIsPositive";
chkIsPositive.Visible = true;
chkIsPositive.Enabled = true ;
ph.Controls.Add(chkIsPositive);
ph.Controls.Add(new LiteralControl(@"</td>"));
}
public override void InstantiateInFooter(PlaceHolder ph)
{
InstantiateInHeader(ph);
}
public override void InstantiateInSelectedItem(PlaceHolder ph)
{
ph.Controls.Add(new LiteralControl(@"<td>"));
Label lblID = new Label();
lblID.ID = "lblID";
ph.Controls.Add(lblID);
ph.Controls.Add(new LiteralControl(@"</td><td>"));
TextBox txtGroup = new TextBox();
txtGroup.ID = "txtGroup";
txtGroup.Visible = true;
txtGroup.Enabled = false;
ph.Controls.Add(txtGroup);
ph.Controls.Add(new LiteralControl(@"</td><td>"));
CheckBox chkIsPositive = new CheckBox();
chkIsPositive.ID = "chkIsPositive";
chkIsPositive.Visible = true;
chkIsPositive.Enabled = false;
ph.Controls.Add(chkIsPositive);
ph.Controls.Add(new LiteralControl(@"</td>"));
}
public override void InstantiateInSeperator(PlaceHolder ph)
{
}
public override void DataBindingOverride(object sender, EventArgs e)
{
PlaceHolder ph = (PlaceHolder)sender;
DataListItem li = (DataListItem)ph.NamingContainer;
int id = Convert.ToInt32(DataBinder.Eval(li.DataItem, "ID"));
string group = (string)DataBinder.Eval(li.DataItem, "Group");
bool isPositive = Convert.ToBoolean(DataBinder.Eval(li.DataItem, "IsPositive"));
switch (this.ListItemType)
{
case ListItemType.Item:
case ListItemType.AlternatingItem:
{
((Label)ph.FindControl("lblID")).Text = id.ToString();
((Label)ph.FindControl("lblGroup")).Text = group;
((CheckBox)ph.FindControl("chkIsPositive")).Text = isPositive.ToString();
break;
}
case ListItemType.EditItem:
case ListItemType.SelectedItem:
{
((TextBox)ph.FindControl("lblID")).Text = id.ToString();
((TextBox)ph.FindControl("txtGroup")).Text = group;
((CheckBox)ph.FindControl("chkIsPositive")).Text = isPositive.ToString();
break;
}
}
}
}
Отсюда я добавил элемент управления на страницу с кодом
public partial class NominalGroupbroke : System.Web.UI.UserControl
{
public void SetNominalGroupList(IList<BONominalGroup> theNominalGroups)
{
XElement data = Serialiser<BONominalGroup>.SerialiseObjectList(theNominalGroups);
ViewState.Add("nominalGroups", data.ToString());
dlNominalGroup.DataSource = theNominalGroups;
dlNominalGroup.DataBind();
}
protected void Page_init()
{
dlNominalGroup.HeaderTemplate = new NominalGroupTemplate(ListItemType.Header);
dlNominalGroup.ItemTemplate = new NominalGroupTemplate(ListItemType.Item);
dlNominalGroup.AlternatingItemTemplate = new NominalGroupTemplate(ListItemType.AlternatingItem);
dlNominalGroup.SeparatorTemplate = new NominalGroupTemplate(ListItemType.Separator);
dlNominalGroup.SelectedItemTemplate = new NominalGroupTemplate(ListItemType.SelectedItem);
dlNominalGroup.EditItemTemplate = new NominalGroupTemplate(ListItemType.EditItem);
dlNominalGroup.FooterTemplate = new NominalGroupTemplate(ListItemType.Footer);
}
protected void Page_Load(object sender, EventArgs e)
{
dlNominalGroup.ItemCommand += new DataListCommandEventHandler(dlNominalGroup_ItemCommand);
}
void dlNominalGroup_Init(object sender, EventArgs e)
{
dlNominalGroup.HeaderTemplate = new NominalGroupTemplate(ListItemType.Header);
dlNominalGroup.ItemTemplate = new NominalGroupTemplate(ListItemType.Item);
dlNominalGroup.AlternatingItemTemplate = new NominalGroupTemplate(ListItemType.AlternatingItem);
dlNominalGroup.SeparatorTemplate = new NominalGroupTemplate(ListItemType.Separator);
dlNominalGroup.SelectedItemTemplate = new NominalGroupTemplate(ListItemType.SelectedItem);
dlNominalGroup.EditItemTemplate = new NominalGroupTemplate(ListItemType.EditItem);
dlNominalGroup.FooterTemplate = new NominalGroupTemplate(ListItemType.Footer);
}
void dlNominalGroup_DataBinding(object sender, EventArgs e)
{
}
void deleteNominalGroup(int index)
{
XElement data = XElement.Parse(Convert.ToString( ViewState["nominalGroups"] ));
IList<BONominalGroup> list = Serialiser<BONominalGroup>.DeserialiseObjectList(data);
FENominalGroup.DeleteNominalGroup(list[index].ID);
list.RemoveAt(index);
data = Serialiser<BONominalGroup>.SerialiseObjectList(list);
ViewState["nominalGroups"] = data.ToString();
dlNominalGroup.DataSource = list;
dlNominalGroup.DataBind();
}
void updateNominalGroup(DataListItem theItem)
{
XElement data = XElement.Parse(Convert.ToString( ViewState["nominalGroups"]));
IList<BONominalGroup> list = Serialiser<BONominalGroup>.DeserialiseObjectList(data);
BONominalGroup old = list[theItem.ItemIndex];
BONominalGroup n = new BONominalGroup();
byte id = Convert.ToByte(((TextBox)theItem.FindControl("lblID")).Text);
string group = ((TextBox)theItem.FindControl("txtGroup")).Text;
bool isPositive = Convert.ToBoolean(((CheckBox)theItem.FindControl("chkIsPositive")).Text);
n.ID = id;
n.Group = group;
n.IsPositive = isPositive;
FENominalGroup.UpdateNominalGroup(old, n);
list[theItem.ItemIndex] = n;
data = Serialiser<BONominalGroup>.SerialiseObjectList(list);
ViewState["nominalGroups"] = data.ToString();
}
void dlNominalGroup_ItemCommand(object source, DataListCommandEventArgs e)
{
DataList l = (DataList)source;
switch (e.CommandName)
{
case "SelectRow":
{
if (l.EditItemIndex == -1)
{
l.SelectedIndex = e.Item.ItemIndex;
l.EditItemIndex = -1;
}
break;
}
case "EditRow":
{
if (l.SelectedIndex == e.Item.ItemIndex)
{
l.EditItemIndex = e.Item.ItemIndex;
}
break;
}
case "DeleteRow":
{
deleteNominalGroup(e.Item.ItemIndex);
l.EditItemIndex = -1;
try
{
l.SelectedIndex = e.Item.ItemIndex;
}
catch
{
l.SelectedIndex = -1;
}
break;
}
case "CancelRow":
{
l.SelectedIndex = l.EditItemIndex;
l.EditItemIndex = -1;
break;
}
case "SaveRow":
{
updateNominalGroup(e.Item);
try
{
l.SelectedIndex = e.Item.ItemIndex;
}
catch
{
l.SelectedIndex = -1;
}
l.EditItemIndex = -1;
break;
}
}
}
Боюсь, там много кода, но он должен быть собран.
Спасибо, если кому-нибудь удастся обнаружить мою глупость.
Класс BONominalGroup (пожалуйста, игнорируйте мое сумасшедшее переопределение getHash, я не горжусь этим).
IAudit может быть просто пустым интерфейсом, и все будет хорошо.
Раньше он унаследовал от другого класса, я убрал его, поэтому здесь может быть нарушена логика сериализации.
public class BONominalGroup
{
public BONominalGroup()
#region Fields and properties
private Int16 _ID;
public Int16 ID
{
get { return _ID; }
set { _ID = value; }
}
private string _group;
public string Group
{
get { return _group; }
set { _group = value; }
}
private bool _isPositve;
public bool IsPositive
{
get { return _isPositve; }
set { _isPositve = value; }
}
#endregion
public override bool Equals(object obj)
{
bool retVal = false;
BONominalGroup ng = obj as BONominalGroup;
if (ng!=null)
if (ng._group == this._group &&
ng._ID == this.ID &&
ng.IsPositive == this.IsPositive)
{
retVal = true;
}
return retVal;
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public override string ToString()
{
return "BONominalGroup{ID:" + this.ID.ToString() +
",Group:" + this.Group.ToString() +
",IsPositive:" + this.IsPositive.ToString() +
"," + "}";
}
#region IXmlSerializable Members
public override void ReadXml(XmlReader reader)
{
reader.ReadStartElement("BONominalGroup");
this.ID = Convert.ToByte(reader.ReadElementString("id"));
this.Group = reader.ReadElementString("group");
this.IsPositive = Convert.ToBoolean(reader.ReadElementString("isPositive"));
base.ReadXml(reader);
reader.ReadEndElement();
}
public override void WriteXml(XmlWriter writer)
{
writer.WriteElementString("id", this.ID.ToString());
writer.WriteElementString("group", this.Group);
writer.WriteElementString("isPositive", this.IsPositive.ToString());
// writer.WriteStartElement("BOBase");
// base.WriteXml(writer);
writer.WriteEndElement();
}
#endregion
}