Gridview 以编程方式将列设置为只读

Gridview Set Column ReadOnly Programmatically

我正在尝试将我的 GridView 中的某些列设置为只读。由于我对几个不同的视图使用相同的 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"));

但是当我尝试作为文本框进行引用时,出现 Object reference not set to an instance of an object. 错误。

TextBox txt = (DataBinder.Eval(e.Row.DataItem, "ID")) as TextBox;
txt.ReadOnly = true;

只是为了好玩,我将名称 "ID" 更改为存储过程未返回的 "SomeID",实际上我收到了与预期不同的错误 DataBinding: 'System.Data.DataRowView' does not contain a property with the name 'SomeID'.

您收到错误消息是因为您返回了一个空的 TextBox 对象,然后试图将其设置为只读。

除非您处于编辑模式,否则 TextBox 控件不会出现在 GridView 中,因此您需要检查 RowState 是否为编辑。注意: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 并定义您的列。 看看这个 post:Allowing one column to be edited but not another

问题已解决!

因为我无法设置 AutoGenerateColumns="False",所以我无法像我尝试的那样将列设置为 ReadOnly。所以我最终做的是在后面的代码中添加 DataKeyNames,因为我需要将每个列设为只读。所以我的代码是这样的:

FormsGridView.DataKeyNames = new string[] { "ID", "Name" };

如果我在 FormsGridView_DataBound 函数中创建的 PageNumbers DropDownList 之后分配了 DataKeyNames,我还在我的代码中进一步移动了它,我分配了一些变量,因为我收到错误 Cannot have multiple items selected in a DropDownList .