Gridview设置列ReadOnly以编程方式

时间:2015-07-15 18:50:24

标签: c# asp.net gridview

我试图在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'.

2 个答案:

答案 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