One of the fantastic new features in WPF is the way many controls can use other controls (and a lot of other things apart from what would usually be regarded as controls) as content. I wanted to try this out, and I created a little sample program. I started with a small WPF application that has a window with a ListBox control in it. Then I created the following class:
public class WowContent: StackPanel {
public WowContent(params string[] entries) {
Orientation = Orientation.Horizontal;
Button button = new Button();
button.Content = "Click!";
Children.Add(button);
listBox = new ListBox();
data = new List<string>(entries);
listBox.ItemsSource = data;
Children.Add(listBox);
}
ListBox listBox;
List<string> data;
}
This class derives from a WPF StackPanel
, which is one of the container classes. In this case, the controls inside the StackPanel
are just “listed”, one behind the other. The extended StackPanel
I created contains a Button
and a ListBox
, which in turn is bound to a list of strings. Now I wanted to initialize the main ListBox
on the form with a list of WowContent
instances. I created the following method for this:
public void BindStuff() {
List<WowContent> list = new List<WowContent>();
list.Add(new WowContent("Hi", "there"));
list.Add (new WowContent());
list.Add (new WowContent("Another", "entry", "with", "more", "text"));
listBox1.ItemsSource = list;
}
My first try was to call this method in the window’s constructor, after the call to InitializeControl
. But I found that this is not possible for some reason, it always results in an exception thrown from the Application.Run
method: Error at element '' in markup file 'Window2.xaml' : Exception has been thrown by the target of an invocation.
I guess this has something to do with the initialization process of XAML windows. I created this method instead, which made things work:
protected override void OnInitialized(EventArgs e) {
base.OnInitialized(e);
BindStuff();
}
The result of all this, magically, looks like this: