根据二维数组识别 WPF 网格中点击了哪个按钮
Identify which button was clicked in WPF gird based on 2D array
我正在构建一个应用程序,它将在二维网格中显示按钮列表,类似于 How to populate a WPF grid based on a 2-dimensional array
挑战在于判断在 buttonClick
事件处理程序中单击了哪个按钮(根据 i、j)。
我最初的想法是让按钮名称包含 i,j 的字符串表示形式(例如 'button_2_3'),但无法使用“{binding ...}”指定名称.
不能使用按钮标签 (button.content
),因为应用程序要求在按钮上显示非唯一标签(按钮标签代表单元格上的棋子,类似于国际象棋,其中 'Q' 标签表示皇后位置)。
最好的替代方法似乎是在按钮的 CommandParameter 属性中存储 row/column 的表示。
我的问题:如何填充每个按钮的 CommandParameter 以便于提取单击按钮的 (i, j)?是否有更好的替代方法将用户定义的数据附加到按钮?
发件人:How to populate a WPF grid based on a 2-dimensional array
<Window.Resources>
<DataTemplate x:Key="DataTemplate_Level2">
<Button Content="{Binding}" Height="40" Width="50" Margin="4,4,4,4" click="buttonClick"/>
</DataTemplate>
<DataTemplate x:Key="DataTemplate_Level1">
<ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource DataTemplate_Level2}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
和
public Window1()
{
List<List<int>> lsts = new List<List<int>>();
for (int i = 0; i < 5; i++)
{
lsts.Add(new List<int>());
for (int j = 0; j < 5; j++)
{
lsts[i].Add(i * 10 + j);
}
}
InitializeComponent();
lst.ItemsSource = lsts;
}
private void buttonClick(object sender, EventArgs e)
{
//do something or...
Button clicked = (Button) sender;
MessageBox.Show("Button's name is: " + clicked.Name);
}
您可以绑定按钮的标签属性
<Button Tag="{Binding}" .../>
并像这样在 Clicked 处理程序中使用它:
private void Button_Click(object sender, RoutedEventArgs e)
{
int value = (int)((Button)sender).Tag;
int row = value / 10;
int column = value % 10;
Debug.WriteLine("Clicked row {0}, column {1}", row, column);
}
使用带有 UniformGrid 的单个 ItemsControl 作为 ItemsPanel 可能会更简单:
<ItemsControl ItemsSource="{Binding}"
HorizontalAlignment="Left" VerticalAlignment="Top">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}" Tag="{Binding}"
Height="40" Width="50" Margin="4" Click="Button_Click"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
并将其 ItemsSource 绑定到 List<int>
:
public MainWindow()
{
InitializeComponent();
var list = new List<int>();
for (int i = 0; i < 5; i++)
{
list.AddRange(Enumerable.Range(i * 10, 5));
}
DataContext = list;
}
您可以为按钮视图模型使用类型而不是 int 列表。
然后在内容和按钮内部绑定 'name' 将在 DataContext 中包含您的对象。
class ButtonViewModel
{
public string Name {get;set;}
public int Value {get;set;}
}
public Window1()
{
List<List<ButtonViewModel>> lsts = new List<List<ButtonViewModel>>();
for (int i = 0; i < 5; i++)
{
lsts.Add(new List<ButtonViewModel>());
for (int j = 0; j < 5; j++)
{
var model = new ButtonViewModel();
model.Value = i * 10 + j;
model.Name = "Q: "+ model.Value;
lsts[i].Add(model);
}
}
InitializeComponent();
lst.ItemsSource = lsts;
}
private void buttonClick(object sender, EventArgs e)
{
//do something or...
Button clicked = (Button) sender;
MessageBox.Show("Button's name is: " + (clicked.DataContext as ButtonViewModel).Name);
}
WPF:
<Window.Resources>
<DataTemplate x:Key="DataTemplate_Level2">
<Button Content="{Binding Name}" DataContext={Binding} Height="40" Width="50" Margin="4,4,4,4" click="buttonClick"/>
</DataTemplate>
P.s。可以使用 "command" 属性 代替按钮“сlick”事件。应该将命令 属性 添加到 ButtonViewModel。这是一种正确的 MVVM 方式。此外,ButtonViewModel 应该实现 IPropertyChanged 接口以通知接口有关值的更改。
我正在构建一个应用程序,它将在二维网格中显示按钮列表,类似于 How to populate a WPF grid based on a 2-dimensional array
挑战在于判断在 buttonClick
事件处理程序中单击了哪个按钮(根据 i、j)。
我最初的想法是让按钮名称包含 i,j 的字符串表示形式(例如 'button_2_3'),但无法使用“{binding ...}”指定名称.
不能使用按钮标签 (button.content
),因为应用程序要求在按钮上显示非唯一标签(按钮标签代表单元格上的棋子,类似于国际象棋,其中 'Q' 标签表示皇后位置)。
最好的替代方法似乎是在按钮的 CommandParameter 属性中存储 row/column 的表示。
我的问题:如何填充每个按钮的 CommandParameter 以便于提取单击按钮的 (i, j)?是否有更好的替代方法将用户定义的数据附加到按钮?
发件人:How to populate a WPF grid based on a 2-dimensional array
<Window.Resources>
<DataTemplate x:Key="DataTemplate_Level2">
<Button Content="{Binding}" Height="40" Width="50" Margin="4,4,4,4" click="buttonClick"/>
</DataTemplate>
<DataTemplate x:Key="DataTemplate_Level1">
<ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource DataTemplate_Level2}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
和
public Window1()
{
List<List<int>> lsts = new List<List<int>>();
for (int i = 0; i < 5; i++)
{
lsts.Add(new List<int>());
for (int j = 0; j < 5; j++)
{
lsts[i].Add(i * 10 + j);
}
}
InitializeComponent();
lst.ItemsSource = lsts;
}
private void buttonClick(object sender, EventArgs e)
{
//do something or...
Button clicked = (Button) sender;
MessageBox.Show("Button's name is: " + clicked.Name);
}
您可以绑定按钮的标签属性
<Button Tag="{Binding}" .../>
并像这样在 Clicked 处理程序中使用它:
private void Button_Click(object sender, RoutedEventArgs e)
{
int value = (int)((Button)sender).Tag;
int row = value / 10;
int column = value % 10;
Debug.WriteLine("Clicked row {0}, column {1}", row, column);
}
使用带有 UniformGrid 的单个 ItemsControl 作为 ItemsPanel 可能会更简单:
<ItemsControl ItemsSource="{Binding}"
HorizontalAlignment="Left" VerticalAlignment="Top">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}" Tag="{Binding}"
Height="40" Width="50" Margin="4" Click="Button_Click"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
并将其 ItemsSource 绑定到 List<int>
:
public MainWindow()
{
InitializeComponent();
var list = new List<int>();
for (int i = 0; i < 5; i++)
{
list.AddRange(Enumerable.Range(i * 10, 5));
}
DataContext = list;
}
您可以为按钮视图模型使用类型而不是 int 列表。
然后在内容和按钮内部绑定 'name' 将在 DataContext 中包含您的对象。
class ButtonViewModel
{
public string Name {get;set;}
public int Value {get;set;}
}
public Window1()
{
List<List<ButtonViewModel>> lsts = new List<List<ButtonViewModel>>();
for (int i = 0; i < 5; i++)
{
lsts.Add(new List<ButtonViewModel>());
for (int j = 0; j < 5; j++)
{
var model = new ButtonViewModel();
model.Value = i * 10 + j;
model.Name = "Q: "+ model.Value;
lsts[i].Add(model);
}
}
InitializeComponent();
lst.ItemsSource = lsts;
}
private void buttonClick(object sender, EventArgs e)
{
//do something or...
Button clicked = (Button) sender;
MessageBox.Show("Button's name is: " + (clicked.DataContext as ButtonViewModel).Name);
}
WPF:
<Window.Resources>
<DataTemplate x:Key="DataTemplate_Level2">
<Button Content="{Binding Name}" DataContext={Binding} Height="40" Width="50" Margin="4,4,4,4" click="buttonClick"/>
</DataTemplate>
P.s。可以使用 "command" 属性 代替按钮“сlick”事件。应该将命令 属性 添加到 ButtonViewModel。这是一种正确的 MVVM 方式。此外,ButtonViewModel 应该实现 IPropertyChanged 接口以通知接口有关值的更改。