我有一个类 BaseTemplate
public abstract class BaseTemplate : ITemplate
这添加了控件,并提供了在继承类中实现的抽象方法。然后继承类根据其数据源添加其html并管理数据绑定。
这一切都很好 - 我让控件显示为正确解析的 html。
问题是基类将控件添加到具有自己的 CommandName 参数的模板中;这个想法是实现自定义模板化 dataList 的类将提供设置 Selected 和 Edit Indexes 的逻辑。此类还管理数据绑定等。它在 Init 方法中设置 datalist 上的所有模板(这是此异常的另一个原因)。
当我点击这些按钮之一时会引发异常 - 我已经尝试在任何地方连接他们的点击和命令事件,以防这是问题所在。我还确保它们的命令名称与任何系统名称都不匹配。堆栈跟踪不包括对我的方法或对象的任何引用,这就是我如此卡住的原因。这是我能想象到的最无益的信息。
真正令人沮丧的是我无法触发断点 - 即问题发生在我单击按钮之后,但在我的代码可以执行之前和之前。
上次发生此异常是当我在用户控件中有此代码并将模板分配给 PageLoad 中的数据列表时。我将这些移入 init 以解决该问题;但是,这是当时存在的一个问题,我不知道是什么原因造成的,更不用说如何解决了(如果不知道什么索引,超出范围的索引并没有真正的帮助。)
异常详情
异常详细信息:System.ArgumentOutOfRangeException:指定的参数超出了有效值的范围。 参数名称:索引
堆栈跟踪:
[ArgumentOutOfRangeException:指定的参数超出了有效值的范围。 参数名称:索引] 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 编写器)+208 System.Web.UI.WebControls.BaseDataList.Render(HtmlTextWriter writer) +30 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter 编写器,ControlAdapter 适配器)+27 System.Web.UI.Control.RenderControl(HtmlTextWriter 编写器,ControlAdapter 适配器)+99 System.Web.UI.Control.RenderControl(HtmlTextWriter writer)+25 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter 作家,ICollection 孩子)+134 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)+19 System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter 作家)+163 System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer)+32 System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter 输出)+51 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter 编写器,ControlAdapter 适配器)+27 System.Web.UI.Control.RenderControl(HtmlTextWriter 编写器,ControlAdapter 适配器)+99 System.Web.UI.HtmlControls.HtmlForm.RenderControl(HtmlTextWriter writer) +40 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter 作家,ICollection 孩子)+134 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)+19 System.Web.UI.Page.Render(HtmlTextWriter 作家)+29 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter 编写器,ControlAdapter 适配器)+27 System.Web.UI.Control.RenderControl(HtmlTextWriter 编写器,ControlAdapter 适配器)+99 System.Web.UI.Control.RenderControl(HtmlTextWriter writer)+25 System.Web.UI.Page.ProcessRequestMain(布尔 includeStagesBeforeAsyncPoint,布尔 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
}