Dim
Dim

Reputation: 4807

Adding dynamic buttons in WPF

I made code that creates buttons dynamically, but how to assign different function to each button?

for (int i = 0; i < Buttons.Count; i++)
{
            Button newBtn = new Button();
            newBtn.Content = Buttons[i];
            newBtn.Name = "Button" + i.ToString();
            newBtn.Height = 23;
            stackPanel1.Children.Add(newBtn);
            newBtn.Click += new RoutedEventHandler(newBtn_Click);
}

private void newBtn_Click(object sender, RoutedEventArgs e)
{
        MessageBox.Show("Hello");
}

Now each button shows "Hello", but I wish it to be "Hello1", "Hello2"....ect.

Upvotes: 2

Views: 9951

Answers (5)

blindmeis
blindmeis

Reputation: 22435

if you could create a collection of objects with DelegateCommands or RelayCommand Property and DisplayName Property - you would just need a ItemsControl bind to this Collection and a DataTemplate for binding a button to Command and Text.

EDIT: just out of my head

 public class MyCommandWrapper
 {
    public ICommand Command {get;set;}
    public string DisplayName {get;set;}
 }

in your viewmodel

 public ObservableCollection<MyCommandWrapper> MyCommands {get;set;}

 MyCommands.Add(new MyCommandWrapper(){Command = MyTestCommand1, DisplayName = "Test 1"};
 ...

in your xaml

  <ItemsControl ItemsSource="{Binding MyCommands}">
   <ItemsControl.Resources>
     <DataTemplate DataType="{x:Type local:MyCommandWrapper}">
       <Button Content="{Binding DisplayName}" Command="{Binding Command}"/>
     </DataTemplate>
   </ItemsControl.Resources>
  </ItemsControl>

EDIT 2: if you need a new dynamic button - just add a new wrapper to your collection

Upvotes: 6

Anatoly Nikolaev
Anatoly Nikolaev

Reputation: 540

  for (int i = 0; i < Buttons.Count; i++)
    {
                Button newBtn = new Button();
                newBtn.Content = Buttons[i];
                newBtn.Height = 23;
                newBtn.Tag=i;
                stackPanel1.Children.Add(newBtn);
                newBtn.Click += new RoutedEventHandler(newBtn_Click);
    }

private void newBtn_Click(object sender, RoutedEventArgs e)
{
       Button btn=sender as Button;
       int i=(int)btn.Tag;

       switch(i)
       {
         case 0:  /*do something*/ break;
         case 1:  /*do something else*/ break;
         default: /*do something by default*/ break;
       }
}

Upvotes: 2

gleng
gleng

Reputation: 6304

private void newBtn_Click(object sender, RoutedEventArgs e)
{
        var button = sender as Button;
        var buttonNumber = button.Name.Remove(0, 6);

        MessageBox.Show("Hello" + buttonNumber);
}

Upvotes: 1

tmp001
tmp001

Reputation: 149

newBtn.Click += new RoutedEventHandler((s,e) => MessageBox.Show("hallo"+((Button)s).Name);

Upvotes: 1

Torben Schramme
Torben Schramme

Reputation: 2140

Check the sender parameter of your newBtn_Click function. It should contain the instance of the button that was clicked. You can cast it to a button and check the name:

private void newBtn_Click(object sender, RoutedEventArgs e)
{
    var btn = sender as Button;
    if(btn != null)
    {
        MessageBox.Show(btn.Name);
    }
}

If you don't want to check the Name property, you can also use the Tag property (http://msdn.microsoft.com/library/system.windows.frameworkelement.tag.aspx) to which you can assign an arbitrary object and check this later:

Button newBtn = new Button();
newBtn.Tag = i;

And later in the click handler:

private void newBtn_Click(object sender, RoutedEventArgs e)
{
    var btn = sender as Button;
    if(btn != null)
    {
        if(btn.Tag is int)
            MessageBox.Show(String.Format("Hello{0}", btn.Tag));
    }
}

I would prefer the solution with Tag because it's more safe than extracting something from a string.

Upvotes: 1

Related Questions