changing DetailsViewMode on Page_Load event

1.1k views Asked by At

I have a simple DetailsView control connected to a data source consisting of two T-SQL queries (which work fine). However, when I try to change the mode (depending on the id in the URL) to "Edit" on Page_Load event nothing shows while "Insert" works fine. Everything seems properly data-bound.

Also, how do I access the BoundField value (the text itself) from code-behind (FindControl always returns null for some reason)? I want to have a default value there when the page loads.

Markup:

<body>
    <form id="form1" runat="server">
    <div class="register" runat="server">
        <asp:DetailsView ID="DV" runat="server" HorizontalAlign="Center" 
            Height="100px" Width="170px" 
            AutoGenerateRows="False" DataSourceID="RegisterUser"
            OnItemCommand="Button_click"
            OnItemInserted="Insert_click" OnItemUpdated="Edit_click">
            <Fields>
                <asp:BoundField DataField="username" HeaderText="Name" 
                    SortExpression="username" />
                <asp:TemplateField HeaderText="Password">
                    <EditItemTemplate>
                        <asp:TextBox ID="Password" runat="server" TextMode="Password" Text='<%# Bind("userPassword") %>'></asp:TextBox>
                    </EditItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="userEmail" HeaderText="Email" 
                    SortExpression="userEmail" />
                <asp:CommandField ShowInsertButton="True" ShowEditButton="True"  />
            </Fields>
        </asp:DetailsView>
        <asp:SqlDataSource ID="RegisterUser" runat="server" 
            ConnectionString="<%$ ConnectionStrings:usersConnectionString %>" 
            InsertCommand="INSERT INTO korisnik(username, userPassword, userEmail) VALUES (@username, @userPassword, @userEmail)" 
            UpdateCommand="UPDATE korisnik SET userPassword = @userPassword, userEmail = @userEmail WHERE (username = @username)">
            <InsertParameters>
                <asp:Parameter Name="username" Type="String" />
                <asp:Parameter Name="userPassword" Type="String" />
                <asp:Parameter Name="userEmail" Type="String" />
            </InsertParameters>
            <UpdateParameters>
                <asp:Parameter Name="userPassword" Type="String" />
                <asp:Parameter Name="userEmail" Type="String" />
                <asp:Parameter Name="username" Type="String" />
            </UpdateParameters>
        </asp:SqlDataSource>
        <asp:Label ID="Message_label" ForeColor="red" Visible="false" runat="server" Text="[messageLabel]"></asp:Label>
    </div>
    </form>
</body>

Code-behind:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        string id = Request.QueryString["id"];
        // EDIT mode
        if (id == "Change_data_button")
        {
            DV.DefaultMode = DetailsViewMode.Edit;
            //DV.DataSource = RegisterUser;
            //DV.DataBind();
            DV.Fields[0].Visible = false; // preventing the value from being changed (one cannot change a username)

            /* found this snippet somewhere but FindControl returns null */
            TextBox user;
            user = (TextBox)DV.FindControl("username");
            user.Text = Session["LoggedUser"].ToString();
        }
        // INSERT mode
        else if (id == "Register_button")
        {
            DV.DefaultMode = DetailsViewMode.Insert;
        }
    }
}
2

There are 2 answers

0
R.C On

You should use: DetailsView.ChangeMode() method to programmatically switch the DetailsView control between edit, insert, and read-only mode.

if (id == "Change_data_button")
        {
            DV.ChangeMode(DetailsViewMode.Edit);
            //DV.DataSource = RegisterUser;
            //DV.DataBind();
         ...
         ...
        }

Also, access the Bound Fields value as::

string _userName = DV.Rows[0].Cells[0].Text.ToString();
0
Alice On

First, I don't see any setting for SelectCommand in SqlDataSource control named RegisterUser, I don't think that you will have data in DetailsView to edit in EditMode.

So you have to set SelectCommand (also SelectParameters if have them) such as the following sample

<asp:SqlDataSource ID="RegisterUser" runat="server" 
            ConnectionString="<%$ ConnectionStrings:usersConnectionString %>" 
            SelectCommand="SELECT * FROM korisnik WHERE username = @username"
            InsertCommand="INSERT INTO korisnik(username, userPassword, userEmail) VALUES (@username, @userPassword, @userEmail)" 
            UpdateCommand="UPDATE korisnik SET userPassword = @userPassword, userEmail = @userEmail WHERE (username = @username)">
    <SelectParameters>
        <asp:Parameter Name="username" Type="String" />
    </SelectParameters>
    <InsertParameters>
        <asp:Parameter Name="username" Type="String" />
        <asp:Parameter Name="userPassword" Type="String" />
        <asp:Parameter Name="userEmail" Type="String" />
    </InsertParameters>
    <UpdateParameters>
        <asp:Parameter Name="userPassword" Type="String" />
        <asp:Parameter Name="userEmail" Type="String" />
        <asp:Parameter Name="username" Type="String" />
    </UpdateParameters>
</asp:SqlDataSource>

Secound, in Page_Load handler, this line user = (TextBox)DV.FindControl("username"); should always be null, because you don't have a control names "username", you have only DataField named "username".

If you want to hide username field in edit mode, you have to set username field as Key of DetailView (DataKeyNames setting). But I suggest that you could set username to be read-only instead of hiding it (set ReadOnly="true" in BoundField). Final, try to get their values in ItemUpdating event handler (OnItemUpdating setting)

Here is the sample as my suggestion:

<asp:DetailsView ID="DV" runat="server" HorizontalAlign="Center" 
    Height="100px" Width="170px" 
    AutoGenerateRows="False" DataSourceID="RegisterUser"
    OnItemCommand="Button_click"
    OnItemInserted="Insert_click" OnItemUpdated="Edit_click"
    OnItemUpdating="DV_ItemUpdating" 
    DataKeyNames="username">
    <Fields>
        <asp:BoundField DataField="username" HeaderText="Name" 
            SortExpression="username" 
            ReadOnly="true"/>
        <asp:TemplateField HeaderText="Password">
            <EditItemTemplate>
                <asp:TextBox ID="Password" runat="server" TextMode="Password" Text='<%# Bind("userPassword") %>'></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="userEmail" HeaderText="Email" 
            SortExpression="userEmail" />
        <asp:CommandField ShowInsertButton="True" ShowEditButton="True"  />
    </Fields>
</asp:DetailsView>

Code-behide:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        string id = Request.QueryString["id"];
        // EDIT mode
        if (id == "Change_data_button")
        {
            DV.DefaultMode = DetailsViewMode.Edit;
        }
        // INSERT mode
        else if (id == "Register_button")
        {
            DV.DefaultMode = DetailsViewMode.Insert;
        }
    }
}
protected void DV_ItemUpdating(object sender, DetailsViewUpdateEventArgs e)
{
    string username = e.Keys["username"].ToString();

    TextBox txtPassword = (TextBox)DV.FindControl("Password");
    string password = txtPassword.Text;

    string email = e.NewValues["userEmail"].ToString();

    RegisterUser.UpdateParameters["userPassword"].DefaultValue = password;
    RegisterUser.UpdateParameters["userEmail"].DefaultValue = email;
    RegisterUser.UpdateParameters["username"].DefaultValue = username;

    RegisterUser.Update();
}