C# 获取由ItemsControl填充的网格的行和列位置

C# 获取由ItemsControl填充的网格的行和列位置,c#,wpf,C#,Wpf,我想用wpf做一个扫雷游戏。我使用以下代码将游戏板设计为按钮网格: <Window.Resources> <DataTemplate x:Key="DataTemplateLevel2"> <Button Content="{Binding}" Height ="30" Width="40" Click ="Execute"/> </DataTemplate> <DataTemplate x:Key

我想用wpf做一个扫雷游戏。我使用以下代码将游戏板设计为按钮网格:

<Window.Resources>
    <DataTemplate x:Key="DataTemplateLevel2">
        <Button Content="{Binding}" Height ="30" Width="40" Click ="Execute"/>
    </DataTemplate>

    <DataTemplate x:Key ="DataTemplateLevel1">
        <ItemsControl ItemsSource ="{Binding}" ItemTemplate="{DynamicResource DataTemplateLevel2}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </DataTemplate>

</Window.Resources>

<Grid>
    <ItemsControl x:Name ="Field" ItemTemplate="{DynamicResource DataTemplateLevel1}" />
</Grid>

List buttonGrid=newlist();
对于(int r=0;r

问题是,当我单击按钮时,我的事件处理程序需要知道按钮的行和列,但是
Grid.GetRow
Grid.GetColumn
始终返回0。我认为这是因为网格只包含一个ItemsControl。如何在仍然允许动态网格大小的情况下获得有意义的行和列值?

您需要详细了解。你的猜测大错特错了。这些按钮没有
Grid.Row
Grid.Column
值,因为您没有明确给它们任何值。此外,如果您这样做,那将是浪费时间,因为它们不在
网格中。它们位于
ContentPresenter
(betcha没有看到!)中,它位于由
ItemsPanelTemplate创建的
StackPanel

无论如何,你不需要做这些。这是你能做的

首先,编写一个简单的类来表示
buttonGrid
中的网格单元。
int?
无法保存您需要的所有信息

public class GridCellItem
{
    public GridCellItem()
    {
    }

    public GridCellItem(int r, int c, int? v = null)
    {
        Row = r;
        Col = c;
        Value = v;
    }

    public int Row { get; set; }
    public int Col { get; set; }
    public int? Value { get; set; }
}
接下来,使用与您所获得的非常相似的代码填充网格:

List<List<GridCellItem>> buttonGrid = new List<List<GridCellItem>>();
for (int r = 0; r < Rows; r++)
{
    buttonGrid.Add(new List<GridCellItem>());

    for (int c = 0; c < Cols; c++)
    {
        buttonGrid[r].Add(new GridCellItem(r, c));
    }
}

Field.ItemsSource = buttonGrid;

ItemsControl的子项不是网格的直接子项。您可以整天为它们提供Grid.Row和Grid.Column值,但这不会产生任何效果,因为它们不是定义了多个行和列的网格的子级。相反,它们是由
ItemsPanelTemplate
创建的StackPanel的子级。没有网格。只有堆叠面板。你想在这里做什么?因为网格不提供索引,所以我想从ItemsControls获取索引。click事件处理程序知道按下了哪个按钮,我只是不知道如何向ItemsControl询问它的位置。
List<List<GridCellItem>> buttonGrid = new List<List<GridCellItem>>();
for (int r = 0; r < Rows; r++)
{
    buttonGrid.Add(new List<GridCellItem>());

    for (int c = 0; c < Cols; c++)
    {
        buttonGrid[r].Add(new GridCellItem(r, c));
    }
}

Field.ItemsSource = buttonGrid;
private void Execute(object sender, RoutedEventArgs e)
{
    var cellItem = ((Button)sender).DataContext as GridCellItem;

    //  Replace this with code that does something useful, of course. 
    MessageBox.Show($"User clicked cell at row {cellItem.Row}, column {cellItem.Col}, with value {cellItem.Value}");
}