WPF For The WinForms Developer: Part 2

Adding WPF Controls

 WPF comes with a good selection of UI Controls, some of which will be familiar to you and some will be brand new. As you work with WPF in Visual Studio you will find that this happens often; there will be things that you are totally familiar with, some that are brand new and some where the goalposts have been moved from the way you did it in WinForms. This last category is probably the trickiest - the change of a Window heading from "Text" to "Title" being a simple example of the sort of thing you'll scratch around for until you become familiar with WPF.

  As with VS 2005 and earlier editions, you have to be working in the Design Pane in order to access, drag and drop the icons for the controls in the Toolbox. And of course, as with earlier editions, you can simply create a new instance of a control by typing in the name of the type of control you need. If you do this via XAML, you will need to place it inside the usual angle brackets used for tags.

 I tried to pick my words very carefully there when I described it as "the name of the type of control". In other words, if you want to add a button then you would type in:

    <Button>

in the XAML Code pane. This creates an instance of a Button, but doesn't assign a Name to that Button instance.

So keep in mind that if you create an instance of a control in XAML by entering text, it doesn't have any value assigned to its Name Property. Of course you can rectify that too in code and set its Name to some value. This is something you can choose to do, depending on whether you need to refer to this control elsewhere. We'll get to Names soon.

  Be aware also that the code editor does not automatically add the closing Tag for you (unlike some of the syntax help you get in a VB file with loops, Try Catch blocks, etc). You have to enter this yourself:

    </Button>

 Nevertheless it's still pretty darn smart because Intellisense will do its best to help you. If you type an opening angle bracket as shown in the screenshot below, you'll see that Intellisense correctly deduces that you probably want to insert the closing tag for the button.


     



  So you may be wondering if it's worth the trouble of creating a control like this in XAML code when you have a perfectly good Toolbox you can drag one from. It seems mostly to be a matter of preference, because whichever way you go about it, you'll end up with additional code in the XAML pane that you can edit, cut and paste as you wish. Most times I think you'll find it most convenient to use the Toolbox option.

 Just while we have that XAML-text-created button on the screen though, let's just look at a couple of things that happen if you choose this route. In the following screenshot you will see that I have typed in the opening and closing tag for a Button.


     


  If you look at the Design Pane you will see that this Button has automatically been placed inside the first cell (Column 0, Row 0) of the Grid. Also the button has been automatically sized to use up all the available space in that cell.

If I click on that Button (either the graphical version in the Design pane or the actual word "Button" in the XAML pane), the Properties Window will display properties for this Button. Notice that there is no Name property for the Button in that Properties Window.


     


 An easy way to remedy this is simply to type a name into that TextBox in the Properties Window and it will automatically be assigned to the control. Notice how the name that has been added via the Properties Window is added to the creation code of the Button in the XAML Code pane. This happens automatically when you either press the Enter key or click elsewhere with the mouse.


     Button assigned a Name






Code Behind

  Do we actually need a Name property, though?
  I think the most accurate answer is "not always".

One situation where you really do have to have a Name property is when you want to be able to refer to this control and do something with it in VB code. In the case of this Button, for example, you will almost certainly want to handle its Click event and the best place to do that is in the VB Code Behind file.

  The path from WinForms to WPF is strewn with changes, multiple choices and Gotchas. These aren't all necessarily bad, but the scope for confusion (and frustration) while you master these things is pretty huge. The interfacing between the XAML code and the VB code is one of the areas that may at times give you pause for thought. For now, though, just note that every object you create in XAML could be created in VB. The reason is that XAML maps directly to classes in the .NET Framework.

  But there's more to this dual code approach than that. If you have used ASP.NET you will be familiar with the idea of Code Behind. And from VB 2005 you will understand how Partial Classes work. Basically, both approaches divide the code into two logical groupings. In the case of VB 2005, the underlying reason is to hide the automatically generated code from developers who don't really need to tinker with it. In WPF the reasoning is slightly different and more like the ASP.NET approach.

 To a large extent the division is based on the core role played by the two languages. XAML is designed to make it possible to create complex graphical interfaces (relatively) easily. The Code Behind is best suited for creating code for events. Now this is a fairly simplistic and artificial line, because rather confusingly you can use either language to fulfill either of these tasks. You wouldn't usually want to, but most things are achievable in either XAML or VB. But if you accept this basic approach (XAML for Graphics, VB for Events) then as a WinForms developer you will probably make your life somewhat easier.

  So, with that in mind I recommend that you get a Name assigned to the control in the XAML code pane - either by typing it directly in to the XAML pane or via the Properties Window. That way you can be sure it will be available to you in the VB file too.

  You don't need to try this experiment out, but feel free to do so if you want to. (And this is something that had me confused for a while). Create a Button control but don't assign any value to the Name property. Now, let's assume that you want to code some action to happen when that button is clicked. As explained, you will almost always want to place this action code in the VB code behind file.

 To view the Code Behind file, identify it in the Solution Explorer and double click it.


     The VB Code Behind File


  If you now look at the Code Window for that VB file (see screenshot below) you will see that the Button is not listed in the left hand combo box.


     Button not listed


And if you can't select it, you won't be able to find its Click event in the right hand combo box either. Coding some action to take place when the Button clicked then will be tricky!

  If however you assign a value to the Button's Name back in the XAML file, that Button instance - and all its usual events - will be available for you to code against in the VB file.

 In other words, doing this:


     Assign a value to the Name property

  will result in this:


     Button appears in the combobox


   But ........ Uh-Oh! There's always a "But", isn't there?
 But be warned that (in the Beta version anyway) there is sometimes a delay between you adding the name to the XAML code and the object instance being visible in the ComboBox when you switch to the VB code behind file. At first I thought it was necessary to rebuild the project for this update to occur, or maybe to save it, but I haven't yet identified the exact cause of the delay and am not 100% convinced it is either of those things.

 There is much more we can (and later will) do with this Button, but for now I simply want to deal with the code behind so we can see a simple example of how we create a control and then wire it up to an event. So, open up the Window1.xaml.vb file which current has almost nothing in it. Click on that left hand combobox and select the GoButton:


     


  If you now move to the right hand combobox you will see the dropdown list of Button events. Most of these are the same ones that you know from earlier editions.
 Select the Click event from the list.


     


  The resulting skeleton of the Click event procedure is very similar to that for VB 2005. In fact, the only change is that the second parameter is now:

    ByVal e As System.Windows.RoutedEventArgs


     Button Click Event Skeleton


I will go into more detail about this parameter later, as it is fundamental to the way that WPF works and its ability to allow several layers of content be used as if they were a single whole. But for now it's sufficient to note this difference exists and leave it at that.

 Purely for the purposes of closure, let's put some relatively meaningless action in this procedure so we can run the project and test that it is all correctly wired up.


     


  Run the project by hitting F5 or use the "Start Debugging" arrow button you are used to from VS 2005 and you should get the MessageBox display when you click the Go Button.

  We'll add some more controls next, do something more meaningful with the button and play around with the positioning of the grid cells and the controls contained inside them. This continues in Part 3.