Alec Sanger
Alec Sanger

Reputation: 4562

Generating and placing buttons in a grid, referencing by x,y coordinates

I need to generate a grid of buttons which will be arranged on a form. The buttons would all execute the same code, but should be able to identify the assigned x and y values of the clicked button. I have 3 ideas on how to achieve this, but I don't know which would be best.

  1. I could create a two-dimensional array of button objects and simply read in the two indexes as the x and y coordinates. This would allow me to easily assign the same code to all buttons, but it isn't THAT flexible as an array.
  2. I could create a list of a list (list of x axes each with a list of y axes) and add buttons to them based on the size of my grid. I don't believe there's a way to assign a single block of code to all of them, though, without pointing each directly to the same event handler (though I suppose I could do the pointing at the time of generating the button object).
  3. Create a new class which stores a button, an X, and a Y value. This class would also contain built-in functionality to handle adding/removing as necessary.

I don't know if there are any simpler solutions - the end result will be a clickable grid that will toggle the clicked object on or off, then feed the coordinates of the "on" buttons into a database.

Upvotes: 1

Views: 4113

Answers (2)

Walt Ritscher
Walt Ritscher

Reputation: 7037

Here is some simple code that does what you want. Wire all the buttons to the same event handler in XAML

<Grid x:Name='gameboardGrid'>
    <Grid.RowDefinitions>
      <RowDefinition Height="1*"/>
      <RowDefinition Height="1*"/>
      <RowDefinition Height="1*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="1*"/>
      <ColumnDefinition Width="1*"/>
      <ColumnDefinition Width="1*"/>
    </Grid.ColumnDefinitions>

<Button Content="Button"  Grid.Column="1" Click="AllButtons_Click"/>
<Button Content="Button" Grid.Column="0" Click="AllButtons_Click"/>
<Button Content="Button"  Grid.Column="2" Grid.Row="1" Click="AllButtons_Click"/>
<Button Content="Button"  Grid.Column="2" Click="AllButtons_Click"/>
        </Grid>

Then in the click hander get the x, y coordinates relative to the LayoutRoot element.

 private void AllButtons_Click(object sender, System.Windows.RoutedEventArgs e) {

  var b = sender as Button;
  // in order to remain hit testable, hide the element 
  // by setting its Opacity property, not the Visibility property

  // also note that semi transparent objects can affect performance
  b.Opacity = b.Opacity >= 1.0 ? 0.0 : 1.0; 
  var locationPoint = b.TransformToVisual(LayoutRoot).Transform(new Point());
  PageTitle.Text = String.Format("{0},{1}",locationPoint.X, locationPoint.Y) ;

}

EDIT

If you want to do it without XAML. Here is the XAML for the grid.

 <Grid x:Name='gameboardGrid'>
        <Grid.RowDefinitions>
          <RowDefinition Height="1*"/>
          <RowDefinition Height="1*"/>
          <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="1*"/>
          <ColumnDefinition Width="1*"/>
          <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
</Grid>

Then add this code to generate the buttons.

public MainPage() {
  InitializeComponent();
  for (int rowCounter = 0; rowCounter < 3; rowCounter++) {
    for (int colCounter = 0; colCounter < 3; colCounter++) {
      var codeButton = new Button();
      Grid.SetRow(codeButton, rowCounter);
      Grid.SetColumn(codeButton, colCounter);

      codeButton.Click += new RoutedEventHandler(AllButtons_Click);
      gameboardGrid.Children.Add(codeButton);
    }
  }
}  

Upvotes: 3

Vlad
Vlad

Reputation: 35594

You could just assign every button a Tag, identifying the button. This way you can make your code independent of the physical location of buttons. This way you could just generate your buttons, add them to the grid, and don't have any other references to them.

I would advice to put into the Tag not the coordinates, but better something that corresponds to the actual semantics of the button (for example, the number which has to be dialled when the button is pressed, or the parameters for the action to be executed).

Upvotes: 1

Related Questions