WPF ListBox

Another old and faithful control that has made the transition to WPF is the ListBox. It’s pretty simple to create a ListBox, and load some values into it.

      <ListBox>

        <ListBoxItem>Item 1</ListBoxItem>

        <ListBoxItem>Item 2</ListBoxItem>

        <ListBoxItem>Item 3</ListBoxItem>

      </ListBox>

Of course the ListBox isn’t much good if you can’t get the value out of it. To do that we’ll have to add a few things.

      <Button Name=ShowSelected Click=ShowSelected_Click>Show Selected</Button>

      <ListBox Name=lbxDemo>

        <ListBoxItem>Item 1</ListBoxItem>

        <ListBoxItem>Item 2</ListBoxItem>

        <ListBoxItem>Item 3</ListBoxItem>

      </ListBox>

 

Here I added a button that would show which item was selected, then I had to give the ListBox a name we could refer to. Following techniques I’ve previously laid out (http://arcanecode.wordpress.com/2007/09/07/adding-wpf-controls-progrrammatically/) I added a click event for the button.

Now, you might think you could just enter something like

      MessageBox.Show(“You Selected “ + lbxDemo.SelectedValue);

And get a message back. But instead what you get is:

 

wpf033

This is because the SelectedValue is actually a ListBoxItem, and not a value. Instead you need to get the content of the ListBoxItem thusly:  

      ListBoxItem lbi = (lbxDemo.SelectedItem as ListBoxItem);

      MessageBox.Show(“You REALLY selected “ + lbi.Content.ToString());

Now you’ll see:

wpf034

Note that you’re not just restricted to ListBoxItems. I could, for example use checkboxes:

      <ListBox Name=lbxCheckMe>

        <CheckBox>Item 1</CheckBox>

        <CheckBox>Item 2</CheckBox>

        <CheckBox>Item 3</CheckBox>

        <CheckBox>Item 4</CheckBox>

      </ListBox>

wpf035

Like other controls, you can stack other controls inside the contents of a ListBoxItem. Let’s get a little fancy, and create a list box with both text and images.

      <ListBox Name=lbxCool>

        <ListBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Anna</TextBlock>

            <Image Source=D:\Presentations\100Anna.jpg Height=100 />

          </StackPanel>

        </ListBoxItem>

        <ListBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Raven</TextBlock>

            <Image Source=D:\Presentations\100Rave.jpg Height=100 />

          </StackPanel>

        </ListBoxItem>

        <ListBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Ammie</TextBlock>

            <Image Source=D:\Presentations\100Ammie.jpg Height=100 />

          </StackPanel>

        </ListBoxItem>

        <ListBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Kids</TextBlock>

            <Image Source=D:\Presentations\100Kids.jpg Height=100 />

          </StackPanel>

        </ListBoxItem>

      </ListBox>

    </StackPanel>

(Note you can use any images, I used a few of my kids and wife.) The result is this:

wpf036

This covers some basics on using a ListBox, enough to get you started with your own lists.

I’m going to DEVLINK!!!

I registered this week to go to DevLink. http://www.devlink.net/ What? You haven’t heard of DevLink? It’s only the best conference bargain on the face of the earth! Two full days of developer sessions, and nationally known speakers. Rocky Lhotka, Rob Howard, Billy Hollis, Kathleen Dollard, just to name a few.

The conference price includes meals, the content on cd/dvd, a Friday night social, and of course a t-shirt! Oh, the price, that’s the best part, all this for $50. Yes, you read that right, FIFTY DOLLARS. I know, I about fainted too, and could kick myself for not knowing about this gem sooner.

The conference is on Friday and Saturday, October 12th and 13th in beautiful Nashville TN. Plenty of stuff for your family to do while you’re geeking it up.

http://www.devlink.net/

DevLink, I’ll be there, ya’ll come! Tell ‘em Arcane Code sent ya.

Adding WPF Controls Progrrammatically

On August 29th I wrote a posting about the StackPanel (http://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:

wpf029

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 (http://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:

wpf030

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.

wpf031

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);

    }

wpf032

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.

WPF Text Controls

WPF Supports several types of text controls for displaying text on your WPF Windows. First is the TextBlock. The text block is very simple, it just displays whatever text you enter on the window. A very basic control for display of titles and what not.

Next up the food chain is the Label. The Label has several advantages over the TextBlock. First, you can change the contents of a label at run time. Let’s take this simple example. First, let’s add a Label to the Button window we created yesterday. In case you missed it, here’s the XAML:

<Window x:Class=WPFSample001.ButtonWindow

    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation

    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml

    Title=Buttons Height=83 Width=194

    >

  <StackPanel>

    <StackPanel>

      <Button Click=Baby_Click>Click Me Baby!</Button>

      <Label Name=lblMyLabel>Before the click</Label>

    </StackPanel>

  </StackPanel>

</Window>

Notice we’ve added a Name property to the Label. This is so we can address it by a specific name within our C# code. After you add the Label here’s an important step: build the application (Build, Build Solution on the menus). You need to do the build so the control will show up in intellisense once you get to the C# window. You can still write the code and make it work, but the intellisense makes it so much easier it’s worth the few seconds to run a build.

OK, you’ve built the app, go to the C# code behind. Locate the event handler for Baby_Click and insert a line to alter the content of the label:

    private void Baby_Click(object sender, RoutedEventArgs e)

    {

      MessageBox.Show(“Hi There!”,“Baby was clicked!”);

    }

If you’ve done traditional WinForms coding in the past, this syntax should look pretty familiar to you. Running the app will produce the expected result. Here’s the before you click:

wpf024

And here’s shot after you click the button:

wpf025 

If you remember the “old days” of WinForms program, you may remember it was possible to use a label as an access key for a textbox. You can still do this with WPF, it just takes a little code. Let’s create a new form, call it LabelForm.

To the LabelForm, add a grid with two rows and two columns, then add two labels and two text boxes. Here’s a sample:

<Window x:Class=WPFSample001.LabelWindow

    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation

    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml

    Title=Label Window Height=95 Width=252

    >

  <Grid>

    <Grid.RowDefinitions>

      <RowDefinition></RowDefinition>

      <RowDefinition></RowDefinition>

    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>

      <ColumnDefinition Width=*></ColumnDefinition>

      <ColumnDefinition Width=2*></ColumnDefinition>

    </Grid.ColumnDefinitions>

    <Label Target={Binding ElementName=FirstBox} Grid.Row=0 Grid.Column=0>_First Box</Label>

    <Label Target={Binding ElementName=SecondBox} Grid.Row=1 Grid.Column=0>_Second Box</Label>

    <TextBox Name=FirstBox Grid.Row=0 Grid.Column=1 />

    <TextBox Name=SecondBox Grid.Row=1 Grid.Column=1>

    </TextBox>

  </Grid>

</Window>

Notice two things. First, we had to give our textboxes a name, via the Name property. Second is the Target property. Inside the property you see curly braces with the word Binding. This is an example of a Markup Extension. Markup Extensions are special WPF classes that are created by the XAML Parser and bound to the item (in this case a Label) we are creating. The items with equal signs, such as ElementName in this example, are named parameters for the Binding class.

I realize that’s a lot of concept in a little space, it might be easier to simply thing of the items in curly braces as a way to define special functionality within WPF.

In this example, the Binding extension binds the label to the textbox passed in the ElementName. When you run the above example, and press the alt key you will see the F (in First) and S (in Second) become underlined.

wpf026 

Pressing F or S will jump you between the text boxes. It’s a bit hard to visualize, but try running the code yourself and you’ll see what I mean.

There’s one more text control I want to mention, the ToolTip. The easy way to create a ToolTip is to simply add it as an item when you create a control. Let’s add a ToolTip to the text boxes.

    <TextBox Name=FirstBox Grid.Row=0 Grid.Column=1 ToolTip=The First Box/>

    <TextBox Name=SecondBox Grid.Row=1 Grid.Column=1 ToolTip=Second Box />

As you can see all I had to do is add a ToolTip= and it’s added.

wpf027 

You can also declare the tooltip as a content item of the main control, using this syntax:

    <TextBox Name=SecondBox Grid.Row=1 Grid.Column=1 >

      <TextBox.ToolTip>

        Second Box

      </TextBox.ToolTip>

    </TextBox>

Why use this second way? Well remember, since it’s content you can get pretty complex with what you declare. Try this out:

    <TextBox Name=SecondBox Grid.Row=1 Grid.Column=1 >

      <TextBox.ToolTip>

        <StackPanel>

          <Label Background=Red Foreground=White>Help Title</Label>

          <TextBlock>This is some descriptive text for the tooltip that tells what it does.</TextBlock>

        </StackPanel>

      </TextBox.ToolTip>

    </TextBox>

Run the app and hover over the second box, and you should see something like this:

wpf028 

Now you begin to gleam a little of the power of WPF, the ability to combine controls and create complex interfaces quickly and easily.

The TextBlock, Label, and ToolTip are the three text controls you can use to display info to your users.

Breaking news: Silverlight 1.0 Released!

Hot off the presses, Microsoft has released Silverlight 1.0! For those unfamiliar with Silverlight, it’s a lightweight add-in that works with most browsers. It allows you to display incredibly rich content in the browser. Version 1.0 uses AJAX libraries to handle multimedia content, games and more.

Read the Microsoft Press Release at:

http://www.microsoft.com/presspass/press/2007/sep07/09-04SilverlightPR.mspx

There is an interview with Scott Guthrie on Channel 9, you can see it here:

http://channel9.msdn.com/showpost.aspx?postid=339594

You can download Silverlight and learn more about it at the Silverlight site:

http://silverlight.net/Default.aspx

or the Microsoft page (slightly different content)

http://www.microsoft.com/silverlight/

Scott Guthrie has a really informative post on his blog:

http://weblogs.asp.net/scottgu/archive/2007/09/04/silverlight-1-0-released-and-silverlight-for-linux-announced.aspx 

If you want to see an example of a Silverlight site, visit the Alabama Code Camp site at:

http://www.alabamacodecamp.com/home.html

Sweet.

The WPF Button

It’s finally time to quit talking about WPF Containers, and start getting into some of the controls. The first one we’ll hit is the hardest working control in show business, the WPF Button.

I’m sure you’re thinking “what’s so hard about a button?” After all, you slap a button tag on a form like this:

<Window x:Class=WPFSample001.ButtonWindow

    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation

    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml

    Title=Buttons Height=83 Width=194

    >

  <StackPanel>

    <Button>Click Me Baby!</Button>

  </StackPanel>

</Window>

I created a window named ButtonWindow, and added a StackPanel with one button. This will give you something like this:

wpf022 

Simple and easy, but there’s much more to the button. First off, you can change the point at which the click event actually fires. The button has a ClickMode property you can set that controls this. The default is “Release”, which pretty much acts as you expect. The other two values are Press and Hover. When the button looks like a button, you would probably want to use release, however it’s possible to morph the button to a graphic of some sort. In that case it might be more intuitive to fire when the button is first pressed, and not when the user releases the mouse.

Speaking of the click, just how do you react to a WPF event in C# anyway? Good question, I thought you’d never ask.

All you have to do is indicate the name of the event you want to respond to, then pass in a string value which is the name of the method to route to. In your XAML, alter the Button line to look like this:

      <Button Click=Baby_Click>Click Me Baby!</Button>

 

Now we need a little C# code to respond. Open the code behind class (in my case ButtonWindow.xaml.cs). Now add a new method:

    private void Baby_Click(object sender, RoutedEventArgs e)

    {

      MessageBox.Show(“Hi There!”,“Baby was clicked!”);

    }

WPF Events must match a certain signature. They will need to have a return type of void (or will be a SUB for you VB folks). They will also accept two arguments, an object that indicates what the sender of the event was, and a set of event arguments encased in the RoutedEventArgs variable, traditionally called e.

Here were doing something pretty simple, and showing a message box.

wpf023 

There’s lots more we can do with the button, but we’ll save that for a more advanced day. Today I just wanted to cover the basics of the button, as it’s one control that will likely see a lot of use in your toolbox.

Wrapping up containers with the WPF WrapPanel

Originally I hadn’t planned to mention the WrapPanel, because in my view it’s not an overly useful control. I have a hard time imagining when you might want to use it, but in playing with it I actually came up with one scenario, perhaps someone will be able to offer some more.

Using the control is easy, simply put <WrapPanel> and it’s ending tag in a Window or Page, then put the controls inside you want. Then as you resize the window, the controls inside will automatically shift around to make use of the available space.

For today’s example, create the WrapPanel tags, and inside put 8 buttons.

  <WrapPanel>

    <Button Width=50>1</Button>

    <Button Width=50>2</Button>

    <Button Width=50>3</Button>

    <Button Width=50>4</Button>

    <Button Width=50>5</Button>

    <Button Width=50>6</Button>

    <Button Width=50>7</Button>

    <Button Width=50>8</Button>

  </WrapPanel>

I then stretched out the window so you can see all 8 horizontally:

wpf019 

Now if I simply resize the window a bit, you’ll see the controls rearrange themselves automatically:

wpf020

And of course I can make them all go vertical if I want:

wpf021 

The one way I can think this might be useful is if you were to create a floating toolbar. In that form it might be handy to have the toolbar buttons moving around. Odds are there are better ways to create a floating toolbar, but if you needed something simple this might be an answer for you.

Other than that one example I can’t think of a lot of uses for it, but if you know some by all means post a comment. Meanwhile at least you’ll be familiar with the WrapPanel container.

The WPF DockPanel

The next container control we need to look at is the DockPanel. It’s a special use control, the individual controls placed inside the DockPanel control can be docked to one of the four sides. Let’s look at an example.

  <DockPanel>

    <Button DockPanel.Dock=Left>Left</Button>

    <TextBlock>Rest of it</TextBlock>

  </DockPanel>

(Note in the code examples I’ve omitted the WINDOW tag, that way you can use this in either Visual Studio or XamlPad) This code produces

wpf016

As you can see, the docked button takes up the entire left side. We could have also set the Dock property to Top, Right, or Bottom. We can have multiple controls with dock property. The order in which they are added is important.

The first control will take up all the space on the docked side first. Then each control will take up the remaining space on the side they are docked on. If multiple controls are docked to the same side, they will be stacked up in the order they were added, the first control being the outermost.

The remaining control added without a dock property will be placed in the middle, and take up all the remaining space. Let’s look at a quick sample that is somewhat realistic.

  <DockPanel>

    <StackPanel DockPanel.Dock=Left>

      <Label>MAIN MENU</Label>

      <Button>Top Left</Button>

      <Button>Left 2</Button>

      <Button>Left 3</Button>

      <Button>Bottom Left</Button>

    </StackPanel>

    <StackPanel DockPanel.Dock=Top Orientation=Horizontal>

      <Label>Secondary Menu</Label>

      <Button>Top Btn 1</Button>

      <Button>Top Btn 2</Button>

    </StackPanel>

    <Grid>

      <Grid.RowDefinitions>

        <RowDefinition></RowDefinition>

        <RowDefinition></RowDefinition>

        <RowDefinition></RowDefinition>

      </Grid.RowDefinitions>

      <Grid.ColumnDefinitions>

        <ColumnDefinition></ColumnDefinition>

        <ColumnDefinition Width=2*></ColumnDefinition>

      </Grid.ColumnDefinitions>

      <Label Grid.Row=0 Grid.Column=0 HorizontalAlignment=Right>First Name:</Label>

      <TextBox Grid.Row=0 Grid.Column=1></TextBox>

      <Label Grid.Row=1 Grid.Column=0 HorizontalAlignment=Right>Last Name:</Label>

      <TextBox Grid.Row=1 Grid.Column=1></TextBox>

    </Grid>

  </DockPanel>

Will produce this lovely window:

wpf017

Now you can begin to glean the usefulness of the DockPanel. You should note because the StackPanel with “Secondary Menu” in it is listed in the XAML after the MAIN MENU StackPanel, it is to the right.

If you simply move the secondary StackPanel above the MAIN MENU one in the XAML, you’ll see the Secondary Menu now goes all the way across, and the Main Menu is now playing second fiddle, thusly:

wpf018

You can add more items to the other sides as well, for example you could put some sort of status bar across the bottom, or another panel over on the right.

As you can see, while it’s not a container control you’ll use every day, the DockPanel can be exteremely useful and flexible in Window design.

Follow

Get every new post delivered to your Inbox.

Join 93 other followers