Hi
In our MouseDown event we want to determine and store which cell was clicked on for processing later (after mouseup, double click etc.)
In normal circumstances it is straightforward - we just use Grid.DisplayLayout.UIElement.ElementFromPoint and use GetContext(typeof(UltraGridCell)) to get the associated cell object.
However if the Cell is merged with some of it's siblings by using the column.MergedCellStyle then the cell returned by GetContext is the first cell in the merged cells not the cell under the mouse point.
Initially I thought I could look at that cell's UIElement and work out which direction the cell that contains the clicked point is by comparing it's Rect and the mouse point. However this is not always possible because the first cell might not be visible if it is scrolled off of the top of the grid hence it doesn't have an associated UIElement.
I notice that a MergedCellUIElement is available in the UIElement hierarchy from the clicked point which contains a list of CellUIElements it spans (in a property called CellElements). If we could access this it would at least be a smaller subset to hittest with the mouse point. However this property is not public. Ah and a useful function called GetCellElemFromPoint is also private, which looking at the source code does exactly that.
The only solution I can see is to scan the UIElement of _every_ cell in the column the returned cell belongs to in order to find the one that contains the clicked point. However this only works for me because I know that I only enable MergedCellStyle on a column. If it was enabled on the whole grid (so they could be merged horizontally aswell) then I would have to search the entire grid to find the target cell, creating cell objects for all cells included in the search that haven't been displayed.
Is there a better way to do this?
(Really I would expect this to be easily available from the grid or griduielement - the fact the UIElement is a merged cell is an implementation detail that I shouldn't have to be concerned about in order to figure out which row/column/cell has been clicked on)
Thanks again
Martin
Hi Martin,
One easy thing you could do is take advantage of the fact the ActiveRow of the grid is set before the MouseDown event fires. So you can check to see if the cell you get is in the ActiveRow and if not, get the cell from the same column in the ActiveRow. Like so:
private void ultraGrid1_MouseDown(object sender, MouseEventArgs e) { UltraGrid grid = (UltraGrid)sender; UIElement lastElementEntered = grid.DisplayLayout.UIElement.LastElementEntered; UltraGridCell cell = lastElementEntered.GetContext(typeof(UltraGridCell)) as UltraGridCell; if (cell != null) { if (cell.Row != grid.ActiveRow) { cell = grid.ActiveRow.Cells[cell.Column]; } } }
Is it the case that the ActiveRow is set when I click with the right mouse button? Doesn't seem to be...
However it appears that calling GetContext(cell) on the UIElement returned from LastElementEntered does return the actual cell that was clicked on, not the first cell in the merged group.
So the solution seems to be to use LastElementEntered rather than the UIElement returned by ElementFromPoint. Do you think this will be the case in all circumstances?
Thanks,