I have a WPF Grid
with some rows and columns, e.g.
<Grid Name="myGrid" MouseMove="OnMouseMove">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
With a handler for MouseMove
in the .cs file, e.g.
private void OnMouseMove(object sender, MouseEventArgs e)
{
var position = e.GetPosition(myGrid);
// What row & col is the mouse over?
}
I want to be able to find which row and column in the grid the mouse is over, is this possible?
[Note: this is a simplified version of the problem, so it looks a little odd to present it in this way - it's part of some drag & drop between grids functionality]
First Method: By typing XAML Code RowDefinitions property and a ColumnDefinition Element for each column inside the Grid. ColumnDefinitions property. By default, GridLines are invisible. For showing the GridLines, set the ShowGridLines property of the Grid to True.
You can span across multiple rows and columns using the Grid. RowSpan and Grid. ColumnSpan attached properties. The default value for both these properties is 1. The Grid will attempt to assign as many row spans or column spans as it can up to the amount specified by the Grid.
A GridView is a control that displays data items in rows and columns. Actually a ListView displays data. By default, it contains a GridView.
XAML doesn't support a GridView element. However, you can use a ListView to create a GridView like UI. The code sample in this article is an example of creating GridView in XAML. You can learn more about ListView control here: ListView in WPF.
I hope you have already find a solution. I faced to the same problem and I found this unanswered post. So I think the next one will be happy to find this solution :
private void OnMouseMove(object sender, MouseEventArgs e)
{
var element = (UIElement)e.Source;
int c = Grid.GetColumn(element);
int r = Grid.GetRow(element);
}
This the following can be done (but shouldn't be used on larger Grids). It is only for Rows, but a second loop can be applied to the columns...
The answer of Nicolas only works if the grid contains some UIElements (whose position in the grid are determined - I guess that would also cause trouble if an element spans several rows/columns).
private void ItemsGrid_MouseMove(object sender, MouseEventArgs e)
{
double y = e.GetPosition(ItemsGrid).Y;
double start = 0.0;
int row = 0;
foreach(RowDefinition rd in ItemsGrid.RowDefinitions)
{
start += rd.ActualHeight;
if (y < start)
{
break;
}
row++;
}
System.Diagnostics.Debug.WriteLine("Row : " + row);
}
public static class GridExtentions
{
public static T Parent<T>(this DependencyObject root) where T : class
{
if (root is T) { return root as T; }
DependencyObject parent = VisualTreeHelper.GetParent(root);
return parent != null ? parent.Parent<T>() : null;
}
public static Point GetColumnRow(this Grid obj, Point relativePoint) { return new Point(GetColumn(obj, relativePoint.X), GetRow(obj, relativePoint.Y)); }
private static int GetRow(Grid obj, double relativeY) { return GetData(obj.RowDefinitions, relativeY); }
private static int GetColumn(Grid obj, double relativeX) { return GetData(obj.ColumnDefinitions, relativeX); }
private static int GetData<T>(IEnumerable<T> list, double value) where T : DefinitionBase
{
var start = 0.0;
var result = 0;
var property = typeof(T).GetProperties().FirstOrDefault(p => p.Name.StartsWith("Actual"));
if (property == null) { return result; }
foreach (var definition in list)
{
start += (double)property.GetValue(definition);
if (value < start) { break; }
result++;
}
return result;
}
}
Usage:
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
var hit = VisualTreeHelper.HitTest(this, e.GetPosition(this));
if (hit == null) { return; }
var grid = hit.VisualHit.Parent<Grid>();
if (grid == null) { return; }
var gridPosition = grid.GetColumnRow(e.GetPosition(grid));
MessageBox.Show(string.Format("Grid location Row: {1} Column: {0}", gridPosition.X, gridPosition.Y));
}
replace Grid.ColumnDefinitions with reference to Grid component
int GetColumn(double point)
{
int index = 0;
foreach(var column in Grid.ColumnDefinitions)
{
if(point > column.Offset && point < (column.Offset + column.ActualWidth))
return index;
index++;
}
return 0;
}
Hope can help. it's working well for my app
public class GridCell
{
public int GridRow { get; set; }
public int GridCol { get; set; }
}
private void Window_MouseMove(object sender, MouseEventArgs e)
{
Point point = e.GetPosition(this.myGrid);
Grid gridTarget = GetLastedGridContainPoint(point, this.myGrid);
Point pointTarget = this.myGrid.TranslatePoint(point, gridTarget);
GridCell cell = GetGridCellContainPoint(pointTarget, gridTarget);
}
private bool IsPointInGrid(Point relativePoint, Grid grid)
{
if (relativePoint.X < 0 || relativePoint.X > grid.ActualWidth ||
relativePoint.Y < 0 || relativePoint.Y > grid.ActualHeight)
{
return false;
}
return true;
}
private Grid GetLastedGridContainPoint(Point relativePoint, Grid gridParent)
{
Grid gridReturn = null;
if (gridParent.Children.Count > 0)
{
Point relativeChildPoint;
foreach (UIElement e in gridParent.Children)
{
if (e is Grid)
{
relativeChildPoint = gridParent.TranslatePoint(relativePoint, (e as Grid));
gridReturn = GetLastedGridContainPoint(relativeChildPoint, (e as Grid));
if (gridReturn != null)
{
break;
}
}
}
}
if (gridReturn == null)
{
if (IsPointInGrid(relativePoint, gridParent))
{
gridReturn = gridParent;
}
}
return gridReturn;
}
private GridCell GetGridCellContainPoint(Point relativePoint, Grid gridTarget)
{
if (!IsPointInGrid(relativePoint, gridTarget))
{
return null;
}
GridCell cell = new GridCell();
double dbStart = 0;
double dbEnd = 0;
if (gridTarget.ColumnDefinitions.Count > 0)
{
for (int i = 0; i < gridTarget.ColumnDefinitions.Count; i++)
{
dbStart = dbEnd;
dbEnd += gridTarget.ColumnDefinitions[i].ActualWidth;
if (relativePoint.X >= dbStart && relativePoint.X < dbEnd)
{
cell.GridCol = i;
break;
}
}
}
dbStart = 0;
dbEnd = 0;
if (gridTarget.RowDefinitions.Count > 0)
{
for (int i = 0; i < gridTarget.RowDefinitions.Count; i++)
{
dbStart = dbEnd;
dbEnd += gridTarget.RowDefinitions[i].ActualHeight;
if (relativePoint.Y >= dbStart && relativePoint.Y < dbEnd)
{
cell.GridRow = i;
break;
}
}
}
return cell;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With