如何在WPF的9×9网格中高效生成带共享事件的8×8按钮网格
WPF动态创建Grid按钮并获取点击位置的实现方案
1. XAML基础布局
先定义9×9的Grid,明确行与列的划分,第0行/列用于显示总和,1-8行/列作为8×8的按钮区域:
<Grid x:Name="MainGrid"> <!-- 9行定义:第0行显示列总和,其余行分配按钮区域空间 --> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!-- 9列定义:第0列显示行总和,其余列分配按钮区域空间 --> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- 总和区域占位标题 --> <TextBlock Grid.Row="0" Grid.Column="0" Text="总和" Padding="5" HorizontalAlignment="Center"/> </Grid>
2. 后台数据结构与按钮创建
先定义存储网格数据的类,再完善动态创建按钮的逻辑:
// 存储网格单元格数据的类 public class GridCell { public int number { get; set; } // 可扩展其他业务字段 } // 全局/类内的二维数组,对应9×9网格的所有数据 private GridCell[,] GridState = new GridCell[9, 9]; private void CreateButtons() { // 初始化8×8按钮区域的数据源 for (int r = 1; r <= 8; r++) { for (int c = 1; c <= 8; c++) { GridState[r, c] = new GridCell { number = r * c }; // 示例初始化值 } } // 循环创建64个按钮 for (int r = 1; r <= 8; r++) { for (int c = 1; c <= 8; c++) { var button = new Button { // 绑定按钮显示内容为单元格数值 Content = GridState[r, c].number.ToString(), // 设置按钮在Grid中的位置 Tag = GridState[r, c] // 将对应数据对象存入Tag,方便后续直接访问 }; Grid.SetRow(button, r); Grid.SetColumn(button, c); // 绑定统一的点击事件处理器 button.Click += GridButton_Clicked; // 将按钮添加到Grid控件中 MainGrid.Children.Add(button); } } // 初始化总和区域显示 UpdateSumCells(); }
3. 统一点击事件处理
通过两种方式获取点击位置/对应数据,满足业务需求:
private void GridButton_Clicked(object sender, RoutedEventArgs e) { if (sender is Button button) { // 方式1:通过Grid附加属性获取按钮所在的行列索引 int row = Grid.GetRow(button); int col = Grid.GetColumn(button); GridState.SomeMethod(GridState[row, col]); // 方式2:直接从Tag获取对应的数据对象(更简洁) if (button.Tag is GridCell cell) { GridState.SomeMethod(cell); // 示例:点击后更新数值并刷新显示 cell.number += 1; button.Content = cell.number.ToString(); UpdateSumCells(); } } }
4. 总和区域更新逻辑
实现行/列总和的计算与动态显示:
private void UpdateSumCells() { // 清除原有总和文本控件 var oldSumCells = MainGrid.Children.OfType<TextBlock>() .Where(tb => (Grid.GetRow(tb) == 0 && Grid.GetColumn(tb) > 0) || (Grid.GetColumn(tb) == 0 && Grid.GetRow(tb) > 0)); foreach (var tb in oldSumCells) { MainGrid.Children.Remove(tb); } // 计算并显示列总和(第0行,1-8列) for (int c = 1; c <= 8; c++) { int colSum = 0; for (int r = 1; r <= 8; r++) { colSum += GridState[r, c].number; } var sumText = new TextBlock { Text = colSum.ToString(), Padding = new Thickness(5), HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; Grid.SetRow(sumText, 0); Grid.SetColumn(sumText, c); MainGrid.Children.Add(sumText); } // 计算并显示行总和(第0列,1-8行) for (int r = 1; r <= 8; r++) { int rowSum = 0; for (int c = 1; c <= 8; c++) { rowSum += GridState[r, c].number; } var sumText = new TextBlock { Text = rowSum.ToString(), Padding = new Thickness(5), HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; Grid.SetRow(sumText, r); Grid.SetColumn(sumText, 0); MainGrid.Children.Add(sumText); } }
5. 调用时机
在窗口Loaded事件中触发按钮创建,确保Grid已完成初始化:
private void Window_Loaded(object sender, RoutedEventArgs e) { CreateButtons(); }
内容的提问来源于stack exchange,提问作者BorZafror
相关产品推荐
相关产品推荐

