On August 29th I wrote a posting about the StackPanel (https://arcanecode.wordpress.com/2007/08/29/stacking-the-deck-with-the-wpf-stackpanel/). A commentor asked “how do you add controls programmatically?” Good question, and it turns out to be quite easy.
Let’s create a sample app, and add a new window. I named mine AddControls. Here’s the XAML:
<Window x:Class=“WPFSample001.AddControls“
xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation“
xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml“
Title=“AddControls“ Height=“114“ Width=“212“
>
<StackPanel Name=“splMain“>
<Button Name=“btnAddMore“ Click=“btnAddMore_Click“>Add Another</Button>
</StackPanel>
</Window>
And here’s what it looks like:
A few things I’d like to point out. I’ve given a name to the StackPanel, so it can be manipulated in our C# code. I also added a handler for the Click event for the button, btnAddMore_Click. I also named the button, although it really wasn’t necessary for this sample.
OK, make sure to build the app so intellisense will work, then let’s jump to the C# code behind. (You may get an error about the click handler for the button not being found, that’s fine just ignore it.)
First, we’ll create an event handler for the button, passing in the sender and routed event args, like I discussed yesterday (https://arcanecode.wordpress.com/2007/09/05/the-wpf-button/) . Then, all we have to do is create a button control and add it to the children collection of the StackPanel, like so:
public void btnAddMore_Click(object sender, RoutedEventArgs e)
{
System.Windows.Controls.Button newBtn = new Button();
newBtn.Content = “A New Button”;
splMain.Children.Add(newBtn);
}
Note in this example I used the fully qualified System.Windows.Controls, I did that just to be explicit where the Button came from. After a new button is created, I set it’s Content property, which in this case will be the text on the button.
In the final line, I add it to the children collection of the StackPanel. When you run it, and press the “Add Another” Button, you will see:
Now we have a new problem. We’ve added a button to the StackPanel, but clicking on it does no good as we haven’t tied it to an event handler. Turns out that’s pretty easy too.
public void btnAddMore_Click(object sender, RoutedEventArgs e)
{
System.Windows.Controls.Button newBtn = new Button();
newBtn.Content = “A New Button”;
newBtn.Click += new RoutedEventHandler(newBtn_Click);
splMain.Children.Add(newBtn);
}
What I did was use a delegate. I added a new RoutedEventHandler and tied it to the click event. The code for the event is in a method named newBtn_Click:
private void newBtn_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(“New Button Clicked!”, “I got pressed.”);
}
The signature for the event handler has to match the signature for a Click event, since that’s what we’re routing to. Here, all I do is display a message box just so you can see something got done. Run it again and press the Add Another button, and the “A New Button” should appear. Press the new button and you should see a message box.
Finally, I want to be clear you can use this technique to add any sort of control. Here I’ve added a Label as well as a button:
public void btnAddMore_Click(object sender, RoutedEventArgs e)
{
System.Windows.Controls.Button newBtn = new Button();
newBtn.Content = “A New Button”;
newBtn.Click += new RoutedEventHandler(newBtn_Click);
splMain.Children.Add(newBtn);
System.Windows.Controls.Label newLbl = new Label();
newLbl.Content = “Hi Mom!”;
splMain.Children.Add(newLbl);
}
I could have created the entire form in C# (or VB.Net) code, adding the StackPanel directly to the “this” object. However, that gets a bit laborious, and I wouldn’t recommend it as a general practice.
Thanks , this came in handy in creating some dynamic user controls
Hi, I just wonder how do add stackpanel control to a window object at run time.
Regards,
John Dang
I tried to make a DataGrid control programatically, and failed. Anyone seen an example like that?
Very Good! simple and clean!
I was able to use your example to implement a app which allows dynamic user control additions to a stackpanel. I would be able to remove a single selected panel, but can’t seem to programmatically find it anywhere. Any thoughts on how to attack this problem?
Hey ,… you haven’t done thorugh MVVM patern. Do you have solution for this in MVVM patern?
so how would you access the details after, say you wanted to get the text of a dynamically added input box ?