获取由ItemScontrol填充的网格的行和柱位置



我正在尝试使用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<List<int?>> buttonGrid = new List<List<int?>>();
for (int r = 0; r < Rows; r++)
{
    buttonGrid.Add(new List<int?>());
    for (int c = 0; c < Cols; c++)
    {
        buttonGrid[r].Add(null);
    }
}
InitializeComponent();
Field.ItemsSource = buttonGrid;

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

您需要阅读有关Grid在WPF中所做的事情。您的猜测很疯狂。这些按钮没有Grid.RowGrid.Column值,因为您没有明确给它们。此外,如果您不在Grid中,那将是浪费时间。他们在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;

完成了所有这些,这是鼠标点击处理程序从单击的项目中获取行,列和价值信息的方式:

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}");
}

最新更新