0
votes

My gridview is binded to an SqlDataSource and populated dynamicaly. I am facing a problem of modifying textbox properties in the edit mode.

protected void gvData_PreRender(object sender, EventArgs e)
{
    if (this.gvData.EditIndex != -1)
        for (int i = 1; i < gvData.Rows[gvData.EditIndex].Cells.Count; i++)
        {
            LinkButton lb = new LinkButton();
            TextBox tb = new TextBox();

            foreach (string pk in Settings.PK)
                if (lb.Text == pk)
                    tb.Enabled = false;
            try
            {
                lb = (LinkButton)gvData.HeaderRow.Cells[i].Controls[0];
                tb = (TextBox)
                    gvData.Rows[gvData.EditIndex].Cells[i].Controls[0];
            }
            catch { }

            if (lb.Text.Contains(Settings.AUTOEXP))
            {
                tb.TextMode = TextBoxMode.MultiLine;
                tb.Rows = 7;
            }

            tb.Text = Truncate.ToText(tb.Text);
            tb.CssClass = "input";
            tb.ID = lb.Text;
        }

    gvData.DataBind();
}

Here the application sets sertain textboxes to multiline and all of them have class "input". With gvData.DataBind(); none of the modifications are applied. If I remove DataBind, it works. But here I face another problem. I am using those values to Update the database.

protected void gvData_RowUpdating(object sender, GridViewUpdateEventArgs e)
{        
    string updateCommand = "UPDATE " + Settings.TABLE + "SET ";
    TextBox tb = new TextBox();

    for (int i = 1; i < gvData.HeaderRow.Cells.Count; i++)
    {
        LinkButton lb = new LinkButton();

        lb = (LinkButton)gvData.HeaderRow.Cells[i].Controls[0];

        try 
        {
            tb = (TextBox)gvData.Rows[e.RowIndex].Cells[i].Controls[0];

            if (tb.Text.Length > 0 && !Settings.PK.Contains(lb.Text))
                try
                {
                    Convert.ToDouble(tb.Text);
                    updateCommand += lb.Text + " = " + tb.Text + ", ";
                }
                catch { updateCommand += lb.Text + " = " + "'" + tb.Text + "', "; } 
        }
        catch { }
    }

    updateCommand = updateCommand.Remove(updateCommand.Length - 2, 2) + " WHERE";

    foreach (string pk in Settings.PK)
    {
        updateCommand += " " + pk + " = :" + pk + " AND";
        DS.UpdateParameters.Add(
            new Parameter(pk, TypeCode.String, e.Keys[pk].ToString()));
    }

    DS.UpdateCommand = updateCommand.Remove(updateCommand.Length - 4, 4);

    gvData.DataBind();
}

Here the application sets the UpdateCommand to the datasource. Values are recieved from the textboxes. If I use gvData.DataBind(); in the PreRender, I am able to get the values from textboxes but styling does not wokr. If I don't use DataBind, styling wotks but textbox values are empty.

Do you have any suggestions? Thank you beforehands!


protected void gvData_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        for (int i = 1; i < e.Row.Cells.Count; i++)
        {
            try
            {
                LinkButton lb = (LinkButton)gvData.HeaderRow.Cells[i].Controls[0];
                lb.ToolTip = select.ToolTip(lb.Text);

                if (lb.Text.Contains(Settings.AUTOEXP))
                {
                    e.Row.Cells[i].ToolTip =
                        Truncate.ToText(e.Row.Cells[i].Text);
                    e.Row.Cells[i].Text =
                        Truncate.ToText(e.Row.Cells[i].Text
                            .Substring(0, 40)) + "...";
                }

                e.Row.DataItem = lb.Text;
                e.Row.Cells[i].Wrap = false;
            }
            catch { }

        }

        if ((e.Row.RowState & DataControlRowState.Edit) > 0)
        {
            for (int i = 1; i < e.Row.Cells.Count; i++)
            {
                LinkButton lb = new LinkButton();
                TextBox tb = new TextBox();

                foreach (string pk in Settings.PK)
                    if (lb.Text == pk)
                        tb.Enabled = false;
                try
                {
                    lb = (LinkButton)gvData.HeaderRow.Cells[i].Controls[0];
                    tb = (TextBox)
                        e.Row.Cells[i].Controls[0];
                }
                catch { }

                if (lb.Text.Contains(Settings.AUTOEXP))
                {
                    tb.TextMode = TextBoxMode.MultiLine;
                    tb.Rows = 7;
                }

                tb.Text = Truncate.ToText(tb.Text);
                tb.CssClass = "input";
                tb.ID = lb.Text;
            }
        }
    }

    if (e.Row.RowType == DataControlRowType.Footer)
        PopulateFooter(e.Row);

}
2
Please validate your input to prevent sql injection attacks and use Double.TryParse() instead of that try catch block.Biff MaGriff
Thank you for your comment. Do you have any suggestions on the issue, though?Nikita Silverstruk
Is the number of columns returning from the database dynamic? I'm wondering why you didn't use a ASP:TemplateColumn for that specific column.rkw
It is dynamic. There are over 30 columns today and the number may change over time.Nikita Silverstruk

2 Answers

1
votes

I would suggest using the onrowdatabound event handler for handling altering the display of your textboxes.

0
votes

Figured it out.

For some reason, the problem was in one line:

tb.ID = lb.Text; 

That code in RowDataBounnd was unnecessary.

The solution is:

In Page_Load add

GridView.DataBind();

RowDataBound:

if ((e.Row.RowState & DataControlRowState.Edit) > 0)
   for (int i = 1; i < e.Row.Cells.Count; i++)
       try
       {
          LinkButton lb = (LinkButton)gvData.HeaderRow.Cells[i].Controls[0];
          TextBox tb = (TextBox)e.Row.Cells[i].Controls[0];

          if (lb.Text.Contains(Settings.AUTOEXP))
          {
              tb.TextMode = TextBoxMode.MultiLine;
              tb.Rows = 7;
          }

          tb.CssClass = "input";
       }
       catch { }

In RowUpdating the value is accessed from the TextBox.