我试图在GridView中将一些列设置为ReadOnly。由于我在几个不同的视图中使用相同的ASPX,我需要在后端代码中执行此操作。我已经看过几篇关于此的帖子,但不确定我做错了什么。我收到了错误Object reference not set to an instance of an object.
这是我的代码:
protected void FormsGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
TextBox txt = (DataBinder.Eval(e.Row.DataItem, "ID")) as TextBox;
txt.ReadOnly = true;
}
}
我也尝试了以下相同的结果。
TextBox txt = (TextBox)e.Row.FindControl("ID");
txt.ReadOnly = true;
我也尝试了以下操作并收到错误Index was out of range. Must be non-negative and less than the size of the collection.
((BoundField)FormsGridView.Columns[1]).ReadOnly = true;
我做错了什么?
编辑:添加了GridView代码
<asp:GridView ID="FormsGridView" runat="server"
DataSourceID="SqlDS1" OnDataBound="FormsGridView_DataBound" AllowPaging="True"
AllowSorting="True" PageSize="1000" onprerender="GridView_PreRender"
CssClass="GridView" onrowcreated="FormsGridView_RowDataBound">
<PagerSettings Position="Top" />
<Columns>
<asp:TemplateField ItemStyle-Wrap="False">
<ItemTemplate>
<asp:HyperLink ID="DeleteButton" runat="server">
<img src="images/delete.png" alt="Delete Item" width="16px" height="16px" style="cursor:pointer;vertical-align:bottom;text-decoration:none" /></asp:HyperLink>
<asp:HyperLink ID="EditButton" runat="server">
<img src="images/edit.png" alt="Edit Item" width="16px" height="16px" style="cursor:pointer;vertical-align:bottom;text-decoration:none" /></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerTemplate>
<div class="pages">
<asp:DropDownList ID="PagingDropDownList" runat="server" AutoPostBack="true"
OnSelectedIndexChanged="PagingDropDownList_SelectedIndexChanged" height="30px" />
</div>
</PagerTemplate>
</asp:GridView>
UpdateCommand也在后端完成:
FormsGridView.AutoGenerateEditButton = true;
SqlDS1.UpdateCommandType = SqlDataSourceCommandType.StoredProcedure;
SqlDS1.UpdateCommand = ("SP");
对我来说,奇怪的是我可以使用以下方法从单元格中提取值:
id = Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "ID"));
但是当我尝试作为TextBox引用时,我收到Object reference not set to an instance of an object.
错误。
TextBox txt = (DataBinder.Eval(e.Row.DataItem, "ID")) as TextBox;
txt.ReadOnly = true;
只是为了踢,我更改了名称&#34; ID&#34; to&#34; SomeID&#34;这不是由存储过程返回的,事实上我确实得到了一个不同的错误DataBinding: 'System.Data.DataRowView' does not contain a property with the name 'SomeID'.
答案 0 :(得分:1)
您收到错误是因为您返回一个空TextBox对象,然后尝试将其设置为只读。
除非您处于编辑模式,否则TextBox控件不会出现在GridView中,因此您需要检查RowState是否为Edit。注意:if
语句可能需要根据您的GridView定义进行调整。
if (e.Row.RowState == DataControlRowState.Edit ||
e.Row.RowState == DataControlRowState.Alternate)
{
TextBox txt = (TextBox)e.Row.FindControl("ID");
txt.ReadOnly = true;
}
您还可以参考此问题:GridView template Column conditionally set to readonly
<强>更新强> 您需要设置AutoGenerateColumns = FALSE并定义列。 看看这篇文章:Allowing one column to be edited but not another
答案 1 :(得分:0)
问题解决了!
因为我无法设置AutoGenerateColumns =&#34; False&#34;正如我试图做的那样,我无法将列设置为ReadOnly。所以我最终做的是在后面的代码中添加DataKeyNames,对于每个我需要ReadOnly的列。所以我的代码是这样的:
FormsGridView.DataKeyNames = new string[] { "ID", "Name" };
如果我在FormsGridView_DataBound函数中创建的PageNumbers DropDownList之后分配DataKeyNames,我还在我的代码中进一步调整了这一点,因为我分配了一些变量,因为我收到了错误Cannot have multiple items selected in a DropDownList
。