如何知道在使用c#以编程方式创建的wpf按钮中单击了哪个按钮

时间:2015-09-19 15:21:50

标签: c# .net wpf button buttonclick

我处于这样一种情况,我必须单击通过c#中的编程动态创建的按钮(因为用户在运行时决定要创建多少按钮)。 我是这样编写的代码:

int runTimeIntegerValue = 6; //Lets say its 6
Button[] childGridSavebutn = new Button[runTimeIntegerValue -1];
for (int j = 0; j < runTimeIntegerValue; j++)
{   
    childGridSavebutn[j] = GenerateButton("Save Table");
    childSmallgrid[j] = generateRowColumnGrid(1, 1);
    Grid.SetColumn(childGridSavebutn[j], 1);
    Grid.SetRow(childGridSavebutn[j], i);
    childSmallgrid[j].Children.Add(childGridSavebutn[j]);

    childGridSavebutn[j].Click += (source, e) =>
    {
        txtBoxOrder[j].Text = "I am from " + j;
        MessageBox.Show("I am from " + j);  //This message always show "I am From 5"
    };

}
private Button GenerateButton(string p)
{
    Button btn = new Button();
    //btn.Name = p;
    btn.Content = p;
    btn.Width = 80;
    btn.HorizontalAlignment = HorizontalAlignment.Center;
    btn.Height = 20;           
    return btn;
}

我弹出一条消息MessageBox.Show("I am from " + i);后知道消息框是从哪个按钮弹出的。它总是弹出5(因为我的最后数是5)。

那么如何通过点击该按钮知道点击了哪个按钮?因为有5个按钮,所以我应该通过点击按钮来知道按钮编号1/2/3/4/5由弹出的消息与受尊重的i位置计时。 (我的意思是点击第i个位置的按钮,当点击第二个按钮时,消息必须显示“我来自2”)

摘要:我有childGridSavebutn [1到5]数组(用户甚至可以决定运行时间为10)。它显示5个按钮,如何知道点击了哪个按钮? (因为它总是弹出第5个)因为我必须接受地生成按钮点击事件。如果我不知道点击了哪个按钮,我将如何做到这一点。最后UI必须像这样重复5次

2 个答案:

答案 0 :(得分:2)

编辑2: 您在评论中要求的内容

<Grid Name="ButtonsContainer">
    <ListBox Name="lb_GlobalList">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <StackPanel>
                        <Button Tag="{Binding SomeNumberValue}" Content="Click me" Click="Button_Click" />
                        <TextBlock Text="{Binding Path=SomeNumberValue, StringFormat={}I am from {0}}" />
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        List<SomeBusinessObject> businessObjects = new List<SomeBusinessObject>();
        for (int i = 0; i < 5; i++)
        {
            businessObjects.Add(new SomeBusinessObject() { SomeNumberValue = i, SomeTextValue = "sample text" });
        }
        lb_GlobalList.ItemsSource = businessObjects;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("I am from " + (sender as Button).Tag.ToString());
    }
}

public class SomeBusinessObject
{
    public int SomeNumberValue { get; set; }
    public string SomeTextValue { get; set; }
}

编辑: 我没有故意使用您的代码,所以您会理解:

  1. 捕获已关闭的变量
  2. 如何以正确的方式使用没有Name属性的控件(事件中的发件人对象)
  3. 如何使用Tag属性存储任何对象 - 甚至其他控件
  4. 你所做的事情在很多层面都是错误的 - DataBindig,DataTemplate等在其他答案中评论
  5. 在我看来,最好的解决方案是使用Button添加要与Tag类关联的元数据,然后按常规方式添加Click事件并使用 (sender as Button)在事件处理程序中访问按钮

    看我的例子

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        for (int i = 0; i < 10; i++)
        {
            Button b = new Button();
            b.Tag = i;
            b.Click += B_Click;
            sp_Container.Children.Add(b);
        }
    }
    
    private void B_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show((sender as Button).Tag.ToString());
    }
    

    在我看来,你在做什么是错的。你应该在特殊情况下需要这个例子。你在WPF中拥有DataBinding功能,使用它!

答案 1 :(得分:1)

当您的当前代码获得一个按钮时,j的值已完成循环,因此对于所有按钮点击,您将获得j的最后一个值。

但它很容易修复。只需改变你的循环:

for (int j = 0; j < runTimeIntegerValue; j++)
{
    childGridSavebutn[j] = GenerateButton("Save Table");
    childSmallgrid[j] = generateRowColumnGrid(1, 1);
    Grid.SetColumn(childGridSavebutn[j], 1);
    Grid.SetRow(childGridSavebutn[j], i);
    childSmallgrid[j].Children.Add(childGridSavebutn[j]);

    childGridSavebutn[j].Click += (source, e) =>
    {
        int j2 = j;
        txtBoxOrder[j2].Text = "I am from " + j2;
        MessageBox.Show("I am from " + j2);
    };
}

int j2 = j;在循环运行时捕获j的值,以便在点击发生时j2正确。