Wtf1sh
Wtf1sh

Reputation: 137

Which cell was clicked in the Grid by coordinates?

I have a Grid with a lot of cells, some of them are empty.I want to determine on which cell was the mouse, when the MouseDown event happened.How is that possible?

Upvotes: 0

Views: 2926

Answers (3)

Sheridan
Sheridan

Reputation: 69979

Here is another option that seems much simpler than the suggested correct answer.

private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
    var element = (UIElement)e.Source;
    int row = Grid.GetRow(element);
    int column = Grid.GetColumn(element);
}

Upvotes: 1

Rob Perkins
Rob Perkins

Reputation: 3130

The first thing to remember is that a control with a transparent background doesn't generate events for its transparent regions. Either set a color for the grid you want, or bind it to the background color of the Window the grid is in, or the events will not fire.

This code sample demonstrates a computational method for determining grid element location given a MouseMove event. The ButtonClick event arguments are very similar. The relevant methods from this sample are ColumnComputation and RowComputation, which take the position on the control and the column or row definitions, for a linear analysis. The sample operates on the InnerGrid UI Element.

Form Class:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }



    private void InnerGrid_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        this.XCoordinate.Text = e.GetPosition(InnerGrid).X.ToString();
        this.YCoordinate.Text = e.GetPosition(InnerGrid).Y.ToString();
        this.ColumnPosition.Text = ColumnComputation(InnerGrid.ColumnDefinitions, e.GetPosition(InnerGrid).X).ToString();
        this.RowPosition.Text = RowComputation(InnerGrid.RowDefinitions, e.GetPosition(InnerGrid).Y).ToString();

    }

    private double ColumnComputation(ColumnDefinitionCollection c, double YPosition)
    {
        var columnLeft = 0.0; var columnCount = 0;
        foreach (ColumnDefinition cd in c)
        {
            double actWidth = cd.ActualWidth;
            if (YPosition >= columnLeft && YPosition < (actWidth + columnLeft)) return columnCount;
            columnCount++;
            columnLeft += cd.ActualWidth;
        }
        return (c.Count + 1);
    }
    private double RowComputation(RowDefinitionCollection r, double XPosition)
    {
        var rowTop = 0.0; var rowCount = 0;
        foreach (RowDefinition rd in r)
        {
            double actHeight = rd.ActualHeight;
            if (XPosition >= rowTop && XPosition < (actHeight + rowTop)) return rowCount;
            rowCount++;
            rowTop += rd.ActualHeight;
        }
        return (r.Count + 1);
    }
}

XAML Form:

<Window x:Name="window" x:Class="GridHitTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Name="OuterBorder"  >
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
            <RowDefinition Height="20"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Column="0" HorizontalAlignment="Center" >X Coordinate</TextBlock>
        <TextBlock Grid.Column="1" HorizontalAlignment="Center"  >Y Coordinate</TextBlock>
        <TextBlock Grid.Column="2" HorizontalAlignment="Center" >Column</TextBlock>
        <TextBlock Grid.Column="3" HorizontalAlignment="Center"  >Row</TextBlock>
        <TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" Name="XCoordinate">kjahsd</TextBlock>
        <TextBlock Grid.Row="1"  Grid.Column="1" HorizontalAlignment="Center" Name="YCoordinate">___ahsdjf</TextBlock>
        <TextBlock Grid.Row="1"  Grid.Column="2" HorizontalAlignment="Center"  Name="ColumnPosition">___ahsdjf</TextBlock>
        <TextBlock Grid.Row="1" Grid.Column="3" HorizontalAlignment="Center"  Name="RowPosition">___ahsdjf</TextBlock>
        <Grid Name="InnerGrid" Margin="20,45,20,10" Grid.ColumnSpan="4" Grid.RowSpan="3" Background="{Binding Background, ElementName=window}"  PreviewMouseMove="InnerGrid_PreviewMouseMove"  >
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
        </Grid>
    </Grid>
</Window>

Upvotes: 1

ΩmegaMan
ΩmegaMan

Reputation: 31636

Place a button into the empty cells (or buttons in all cells, but style hidden when other items are present and make the cell not empty). Then when the user clicks on the cell, report the cell such as

private void OnButtonClick(object sender, RoutedEventArgs e)
{
    var buttonClicked = sender as Button;

    var gridRow = (int)buttonClicked.GetValue( MyGrid.RowProperty );
    var gridColumn = (int)buttonClicked.GetValue( MyGrid.ColumnProperty );

}

Upvotes: 1

Related Questions