如何从 WPF 中网格内的标签中获取行和列信息?
Posted
技术标签:
【中文标题】如何从 WPF 中网格内的标签中获取行和列信息?【英文标题】:How to grab row and column info from a label inside a grid in WPF? 【发布时间】:2011-06-30 22:10:31 【问题描述】:我有一个 3x3 网格,用作井字游戏的游戏板。每个网格都有一个标签,可以显示“X”“O”或“”。这些标签中的每一个都包含它们所在位置的行和列信息。我正在尝试从代码文件中获取该信息。到目前为止,我有:
<Label Grid.Row="0" Grid.Column="0" Name="lblZeroxZero" MouseDown="lblZeroxZero_MouseDown" FontSize="72" Padding="5" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<Label Grid.Row="0" Grid.Column="1" Name="lblZeroxOne" MouseDown="lblZeroxOne_MouseDown" FontSize="72" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
<Label Grid.Row="0" Grid.Column="2" Name="lblZeroxTwo" MouseDown="lblZeroxTwo_MouseDown" VerticalContentAlignment="Center" FontSize="72" HorizontalContentAlignment="Center" />
<Label Grid.Row="1" Grid.Column="0" Name="lblOnexZero" MouseDown="lblOnexZero_MouseDown" HorizontalContentAlignment="Center" FontSize="72" VerticalContentAlignment="Center" />
<Label Grid.Row="1" Grid.Column="1" Name="lblOnexOne" MouseDown="lblOnexOne_MouseDown" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="72" />
<Label Grid.Row="1" Grid.Column="2" Name="lblOnexTwo" MouseDown="lblOnexTwo_MouseDown" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="72" />
<Label Grid.Row="2" Grid.Column="0" Name="lblTwoxZero" MouseDown="lblTwoxZero_MouseDown" FontSize="72" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />
<Label Grid.Row="2" Grid.Column="1" Name="lblTwoxOne" MouseDown="lblTwoxOne_MouseDown" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="72" />
<Label Grid.Row="2" Grid.Column="2" Name="lblTwoxTwo" MouseDown="lblTwoxTwo_MouseDown" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="72">
这些是我的标签,我想在我的代码文件中获取 Grid.Row 和 Grid.Column 信息。当我输入 lblZeroxZero 时。智能感知不会显示任何包含行和列信息的属性。有谁知道如何获取此信息?我必须从数据网格而不是标签访问它吗?
编辑:更多信息
在我的代码文件中我有这个方法(尚未完成)
private int[] GetLabelPosition(Label lbl)
int[] rowColumnInfo = new int[2];
if (lbl.Name == "lblZeroxZero")
rowColumnInfo[0] = 0;
rowColumnInfo[1] = 0;
else if (lbl.Name == "lblOnexZero")
rowColumnInfo[0] = 1;
rowColumnInfo[1] = 0;
return rowColumnInfo;
目前,我知道如何获取标签的行和列信息的唯一方法是查看其名称。我想获得 Grid.Row 和 Grid.Column 信息,而不必为每个标签名称创建一堆特定案例。
【问题讨论】:
【参考方案1】:在Grid
使用附加属性GetRow
和GetColumn
。示例
int row = Grid.GetRow(lblZeroxZero);
int column = Grid.GetColumn(lblZeroxZero);
更新
在你的情况下,你可以做类似的事情
private int[] GetLabelPosition(Label lbl)
return new int[] Grid.GetRow(lbl), Grid.GetColumn(lbl) ;
【讨论】:
【参考方案2】:正如 OJ 建议的那样,您应该使用数据绑定。这让您可以将在屏幕上呈现游戏的问题与管理游戏内部逻辑的问题分开。
您需要创建一个 Cell
类来公开 Row
、Column
和 Owner
属性。该类将需要实现INotifyPropertyChanged
,以便当Owner
发生更改时,它可以通过引发PropertyChanged
事件来提醒UI。最后,该类将实现一个SelectCellCommand
,它将在执行单元格时为它适当地设置Owner
(一旦设置了单元格的所有者,其CanExecute
属性将设置为false)。
您将创建一个包含其中九个Cell
s 的集合,并将Row
、Column
和Owner
属性设置为适当的初始值。你所有的游戏逻辑(例如,轮到谁了?有人赢了吗?)都会检查这个集合。
在 UI 中,您将创建一个绑定到 Cell
s 集合的 ItemsControl
。控件中的每个项目都将是网格中的一个单元格。
您将ItemsPanel
设置为Grid
,这将告诉ItemsControl
如何布置其项目。您将创建一个ItemContainerStyle
,将Grid.Row
和Grid.Column
附加属性分配给项目的容器 - ItemsControl
为ItemsSource
中的每个对象创建一个ItemsPresenter
,Grid.Row
和必须在此对象上设置Grid.Column
属性,以便Grid
看到它们并知道将它们放在哪里。
最后,控件将包含一个ItemTemplate
,它描述了每个项目的显示方式。我正在使用一个Button
(因为您希望有一个在用户单击它时执行的命令),其中包含一个TextBlock
,它在Owner
中显示X 或O。
它可能看起来像这样:
<ItemsControl ItemsSource="Binding StaticResource Cells">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
<ItemsPanel.ItemContainerStyle>
<Style TargetType="ItemPresenter">
<Setter Property="Grid.Column" Value="Binding Column"/>
<Setter Property="Grid.Row" Value="Binding Row"/>
</Style>
</ItemsPanel.ItemContainerStyle>
<ItemsPanel.ItemTemplate>
<DataTemplate DataType="local:Cell">
<Button Command="Binding SelectCellCommand" VerticalContentAlignment="Center" HorizontalContentAlignment="Center">
<TextBlock FontSize="72" Source="Binding Owner"/>
</Button>
</DataTemplate>
</ItemsPanel.ItemTemplate>
</ItemsControl>
</ItemsControl>
为什么要经历这一切?
好吧,让我们看看您当前的设计存在哪些问题:
如果您想更改设计中单元格的布局,您需要修复九个不同的控件。在这里,您只需更改单元格的DataTemplate
。
不需要九个不同的事件处理程序。因为按钮绑定到作为Cell
属性的命令对象,所以您不需要执行任何方法来找出用户刚刚单击了哪个单元格- 命令是 的方式。此外,一旦设置了Owner
,您就可以非常简单地禁用该命令(及其按钮)。
您的所有游戏逻辑都可以查看一个简单的数据结构 - Cell
对象的集合 - 而无需关心 UI 的工作方式。
最后,也是最重要的一点,数据绑定是 WPF 应用程序开发的核心。这使得开发 WPF 应用程序比实现 WinForms 应用程序容易得多。如果你在学习 WPF 时没有学习绑定,那你就是在浪费时间。
【讨论】:
【参考方案3】:Meleak 的第一个答案 +1,但我还想建议您不要使用代码隐藏,而是使用数据绑定?它将大大简化您的代码。
【讨论】:
我是数据绑定的新手。能举个小例子吗? 我可以把一个放在一起,但不能等到以后;)以上是关于如何从 WPF 中网格内的标签中获取行和列信息?的主要内容,如果未能解决你的问题,请参考以下文章