View Single Post
  #4 (permalink)  
Old April 22nd, 2005, 04:03 PM
noah noah is offline
Registered User
 
Join Date: Apr 2005
Location: , , .
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I've just found what you might feel is a better solution; I certainly feel so. It's not perfect: I'd rather see an attribute or EditItemStyle template on the BoundColumn, but it works pretty nicely.

If you add an event handler to the grid's PreRender event, the TextBox will have already been created and you can modify its properties before it is rendered for the client. I am only latching the PreRender event from the Edit command in this sample, so the check on the editing flag is unnecessary here. However, if you were doing something else in that event, it would be required, so I included it. Also note that I am working with the second column.

I'm slightly dissatisfied that we have to specify the width and mode in the page class but this is the cleanest solution I've found. Scratch that -- while typing this up, I got enough of an itch to try deriving BoundColumn and adding a couple of attributes. It seems to work nicely. Using EditMode as the TextBoxMode enum type "just works", apparently using reflection somewhere internally to find the right type.

I'll leave both solutions in this post for academic purposes. If anyone knows of a situation where a BoundColumn will not have the TextBox as the first control, please chime in, as that's an assumption in the code below.

First solution: modify the cell programmatically
--
private bool editing = false;
private int editingIndex;
private Unit editingWidth = new Unit(20, UnitType.Em);

private void someDataGrid_EditCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
  someDataGrid.EditItemIndex = e.Item.ItemIndex;
  BindGrid();
  editing = true;
  editingIndex = e.Item.ItemIndex;
  someDataGrid.PreRender += new EventHandler(someDataGrid_PreRender);
}

private void someDataGrid_PreRender(object sender, EventArgs e)
{
  if (editing)
  {
    ((TextBox)someDataGrid.Items[editingIndex].Cells[1].Controls[0]).Width =
      editingWidth;
    ((TextBox)someDataGrid.Items[editingIndex].Cells[1].Controls[0]).TextMode =
      TextBoxMode.MultiLine;
  }
}
--


Second, better solution: derive BoundColumn and leave it mostly untouched, adding a couple of attributes
--
namespace CustomWebControls
{
  [DefaultProperty("Text"),
    ToolboxData("<{0}:CustomBoundColumn runat=server></{0}:CustomBoundColumn>")]
  public class CustomBoundColumn : System.Web.UI.WebControls.BoundColumn
  {
    private string editWidth = "";
    public string EditWidth
    {
      get { return editWidth; }
      set { editWidth = value; }
    }

    private TextBoxMode editMode = TextBoxMode.SingleLine;
    public TextBoxMode EditMode
    {
      get { return editMode; }
      set { editMode = value; }
    }

    public override void InitializeCell(TableCell cell, int columnIndex, ListItemType itemType)
    {
      base.InitializeCell (cell, columnIndex, itemType);
      if (itemType == ListItemType.EditItem)
      {
        if (editWidth != "")
          ((TextBox)cell.Controls[0]).Width = new Unit(editWidth);
        ((TextBox)cell.Controls[0]).TextMode = editMode;
      }
    }
  }
}
--
<cwc:CustomBoundColumn DataField="someField" SortExpression="sort_order" HeaderText="Some Header" EditWidth="20em" EditMode="MultiLine">
  <HeaderStyle Width="20em"></HeaderStyle>
  <ItemStyle Width="20em"></ItemStyle>
</cwc:CustomBoundColumn>
--

I hope it helps!

Thanks,
-Noah