Keeping columns from being sized wider than the grid

3 posts, 1 answers
  1. Bill
    Bill avatar
    11 posts
    Member since:
    Jan 2011

    Posted 02 Mar 2012 Link to this post

    The issue at had is pinned columns - these stay unmoving on left side of the grid regardless of how you scroll, which means that if you stretch the right edge of a pinned column off the right side of the grid and let go, the edge is out of reach and you can't scroll over to get it, which effectively makes all columns to the right of it permanently unavailable.  This is obviously undesireable and I wish to avoid it.

    The columns must remain pinned and resizeable - up to but not including the ability to drag the edge of the column off the edge of the grid.  Note that the allowable width is not fixed; it depends on both the width of the grid and the current position of the column within it.  The column might be the second or third columnin the grid, with the (also pinned) columns to its left being arbitrarily resizeable as well.

    My plan in dealing with this would be to react to the ColumnWidthChanging or ColumnWidthChanged events and constrain/restore the column to a decent width, but I ran into an unexpected problem - I can't figure out how to get the location on-screen of a given column!  Without knowing where the column's left edge is I can't determine how wide to allow it to be.  Given a GridDataCellElement I could ask for its ControlBoundingRectangle, but I don't know how to get a GridDataCellElement from an arbitrary column.  The only one I seem to have direct access to is CurrentCell, which may or may not be in the column I'm interested in.

    So - can anyone tell me how to get an arbitrary GridDataCellElement, or otherwise determine the pixel location of a column's left edge?
  2. Bill
    Bill avatar
    11 posts
    Member since:
    Jan 2011

    Posted 06 Mar 2012 Link to this post

    Alright, an update.  The following code appears to have the desired effect:
    void radGridView_ColumnWidthChanged(object sender, System.Windows.Forms.ColumnWidthChangedEventArgs e)
    {
        if (!radGridView.Columns[e.ColumnIndex].IsPinned) return;
     
        int left = 30;
        int right = radGridView.Width;
        for (int i = 0; i <= e.ColumnIndex-1; i++)
            left += radGridView.Columns[i].Width;
     
        if (radGridView.Columns[e.ColumnIndex].Width > right - left)
            radGridView.Columns[e.ColumnIndex].Width = right - left;
    }

    Despite the event name, this is actually called constantly while the column is being resized, which is odd but actually gives me a nicer-looking behavior as a result, since it prevents the user from even trying to drag the column beyond the limits.  (I was not able to replicate the effect with the more natural-seeming ColumnWidthChanging event because it was less amenable to me resizing the column mid-operation.)

    There is one detail of this solution that could be improved upon, though: that 30 there.  It's meant to account for the width of the row selection area to the left of all columns; the number itself was chosen completely arbitrarily, and just happened to be large enough to account for the row selection area and to give me a pleasant-looking bit of extra margin besides.  This is dependent upon the width of that leftmost area never changing, though, and I dislike that sort of assumption.  How does one programmatically determine the width of that area?
  3. Answer
    Jack
    Admin
    Jack avatar
    2333 posts

    Posted 07 Mar 2012 Link to this post

    Hello Bill,

    I am glad to hear that you have found a solution for this issue.

    You can get the row header width by using the RowHeaderColumnWidth property of GridTableElement:
    int rowHeaderWidth = this.radGridView1.TableElement.RowHeaderColumnWidth;

    Regarding your initial question, you can get the cell element for a certain column and row by using the GetCellElement method:
    GridCellElement cell = this.radGridView1.TableElement.GetCellElement(this.radGridView1.MasterView.TableHeaderRow, this.radGridView1.Columns["Name"]);
    if (cell != null)
    {
        //...
    }

    However, please note that RadGridView uses UI virtualization and not all data cells have corresponding cell elements. When scrolling or applying data operations cell elements are reused for other cells. All this improves the performance and lowers the memory consumption. So, we do not recommend using the GetCellElement method.

    When using a table layout, you can get cell dimensions by using the GetColumnOffset and GetColumnWidth methods of TableViewRowLayout. Here is a sample:
    TableViewRowLayout tableLayout = this.radGridView1.TableElement.ViewElement.RowLayout as TableViewRowLayout;
    int offset = tableLayout.GetColumnOffset(this.radGridView1.Columns[2]);
    int width = tableLayout.GetColumnWidth(this.radGridView1.Columns[2]);

    I hope this helps.

    Kind regards,

    Jack
    the Telerik team
    RadControls for WinForms Q1'12 release is now live! Check out what's new or download a free trial >>
Back to Top