Zoek

Uitgebreid zoeken Artikelen per auteur

  

Getting started with Windows Presentation Foundation

Getting started with Windows Presentation Foundation

So you're a developer and you want to get started with Windows Presentation Foundation (a.k.a.) Avalon? This article will just touch on some of the basics of WPF.

Installing WPF

I always use VirtualPC images for running beta material. This wa,y if the code won’t uninstall, there are no worries, just start a new image. You never have to reinstall the host machine. Here are the steps I took to get WPF installed:

  1. Create a fresh VirtualPC image with WindowsXP SP2. I read that you can also use Windows Server 2003 if you wish.
  2. Install Visual Studio 2005. I use Professional edition, but the beta's also work with the Visual Studio Express editions.
  3. Download the WinFX software developer kit at: http://msdn.microsoft.com/windowsvista/getthebeta/default.aspx 
    I've downloaded the WinFX RTC plus the VS2005 extensions.
    Note that if you want to install the VS2005 extensions you also need to download the Windows SDK beta.
    If you don't install the SDK the VS2005 extensions will show a message saying that you need to install the Windows SDK and then also make sure that you install the beta SDK, the regular SDK will not suffice!
    Feels like my WindowsXP machine is being turned into a Vista machine already :-))
  4. Install the WinFx RTC download. The installer will want to download another 16MB of data, so make sure your VirtualPC environment has Internet access.
  5. Install the Windows SDK beta.
  6. Install the VS2005 Extensions package.
  7. Install the VS2005 Extensions for Windows Workflow Foundation. These are obviously optional for playing around with the WPF beta, but since we're setting up a play area we might as well get it complete.

Done? Okay, time to test to see if all is well.

Time to make a little test XAML application.

It’s time to make a little test XAML application, and there is of course no substitute for a Hello World application.

  1. Use notepad to create a file called 'test.xaml'
  2. Copy or type the code below into file.

          xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
       Hello World!

  3. Save
  4. Double click the file.
  5. Yeah! A real life XAML application.

XAML != WPF

You don't need to use XAML to program WPF. Quite the contrary, everything you can do with XAML you can do with C#. It's just a matter of using the right tool for the right job. It doesn't make much sense to do all the layout code in C#, XAML will hopefully do a better job there. Anyway, just to prove the point I have to start where every new technology starts: Hello World!

I've installed all the necessary tools. I've started VS2005 and created a new WinFx application.
The application by default holds references to all relevant assemblies, these being:

  1. PresentationCode
  2. PresentationFramework
  3. WindowsBase

The names of these assemblies don't look very RTM-like, so I have to assume they'll change in one of the upcoming CTP's or RTM.

The names of these assemblies don't look very RTM-like

I like to start as clean as possible, so I throw out all the files under the properties folder and also the default created MyApp.xaml and Class1.xaml.

Now add a new class called HelloWorld:

using System;
using System.Windows;  //This is the WPF namespace

namespace HelloWorld
{
  public class HelloWorld
  {
    [STAThread]
    public static void Main()
    {
      // This is the System.Windows.MessageBox
      MessageBox.Show("Hello SDN!");           
    }
  }
}

Startup the application and go!

As you can see the root namespace for WPF is ‘System.Windows’. Already all of the basic Windows stuff is available, so of course the MessageBox can be used to display a nice little ‘Hello SDN’ message.

By default Visual Studio will place the layout information of a form in a XAML-file and the code in a code-behind file, much like ASP.NET webforms.

Windows.Application

So is an WPF application just one class, or one XAML-file? Well it can be, but more often than not your application will be a lot larger. You’ll want to do more with the application and you want the application to be more robust. This is where the ‘Windows.Application’ class comes in. Your application should make use of this class, since it allows for lifetime tracking through events like StartUp and SessionEnding and methods like Run.

We can expand our hello world to:

using System;
using System.Windows;

namespace HelloWorld
{
  public class MyApp : Application
  {
    [STAThread]
    static void Main(string[] args)
    {
      MyApp app = new MyApp();
      app.Startup += app.OnApplicationStart;
      app.Run(args);
    }

    void OnApplicationStart(
      object sender, StartupEventArgs e)
    {
      Window w = new Window();
      w.Title = "Mark says: Hello World!";
      w.Show();
    }
  }
}

Above is just the code I could come up with, but with a little bit of digging around you can find the code that Visual Studio uses for initializing the application:

public partial class MyApp :
  System.Windows.Application
{
  ///


  /// InitializeComponent
  ///

  public void InitializeComponent()
  {
    this.StartupUri = new
      Uri("Window1.xaml", System.UriKind.Relative);
    Uri resourceLocater = new
      Uri("myapp.baml",
          System.UriKind.RelativeOrAbsolute);
    Application.LoadComponent(this, resourceLocater);
  }

  ///
  /// Application Entry Point.
  ///

  [System.STAThreadAttribute()]
  public static int Main(string[] args)
  {
    System.Threading.Thread.CurrentThread.
      SetApartmentState(
        System.Threading.ApartmentState.STA);
    MyApp app = new MyApp();
    app.InitializeComponent();
    return app.Run(args);
  }
}

As you can see some resources are initialized in the InitializeComponent. By default the VS2005 WinFx project sets up some resources, which you can find under the 'Properties' folder. Also an URI is set to track the initial window. This URI is the window that will be started when app.Run(..) is executed. This can also be accessed through the project properties.

Controls in controls

With WPF we are far more flexible in creating UI solutions. since now almost every control can contain other controls. The classic example will be of course the button. A button cannot just have a text on the surface of the button, it can just as easily have an image.

An example of a button with text:

And an example of a button with image:

A lot of buttons will have an image and also some text. So with our HTML background we'll probably attempt:

Wrong!

A button can contain controls, but has no 'knowledge' of how to produce a layout for multiple controls. WPF has special controls that provide a layout implementation. These are panels. There are four kinds of panels:

  1. DockPanel
  2. StackPanel
  3. Grid
  4. Canvas

The same is actually true of the Window control. A Window has no 'default' knowledge of layout. VS2005 will by default add a 'Grid' control as the root panel.

A StackPanel is the easiest to use. It will stack items either horizontally or vertically. In our button example we would want to use the StackPanel as the child of our Button.

Notice that we don't need the
tag anymore. The linefeed is really layout information and our StackPanel is in charge of layouting the content. If, however, we have a lot of text, then we could put a newline within the TextBlock.

A Grid offers more options and acts much more like a table with rows and columns. I'll show a quick example:


 
   
   
   
 

 
   
   
   
 

 
     Top left
 

 
    Middle
 

 
    Bottom right
 

      Source=
      "C:\Documents and Settings\Mark\Desktop\
       banner.jpg"
    Name="image1"
    Width="50"
    Grid.Column="1"
    Grid.Row="0"/>

As you can see the content of an actual cell is not placed in the cell, but instead the content is listed below the column and row definitions. I must say that I'm still in the process of getting used to this notation.

The DockPanel allows you to dock content to a border of the window. And the Canvas panel performs no layout functionality, you're in charge of all layout matters, much like the way 'regular' WinForms let you do all the layouting.

EventBubbling

With controls in controls it becomes quite tricky when you try and implement an event handler. In the traditional WinForms environment embedded controls would each have to implement their own event handler. Not very smart! This is where WPF introduces EventBubbling. People who have done scripting in Internet Explorer will find this very familiar. The concept is that an event handler may not be implemented on a GUI-control, but can also be implemented on the parent of that GUI-control. When an event is fired it will traverse the tree from child to parent to parent to parent until it reaches the top control, usually the window.

Let's look at a demo.

Below is the XAML file for Window1.

  xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
  xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
  Title="Demo3.EventHandling">
  
          VerticalAlignment="Stretch" Click="button1_Click"
      HorizontalAlignment="Stretch"
      Grid.Column="0" Grid.ColumnSpan="1"
      Grid.Row="0" Grid.RowSpan="1"
      Margin="80,85,77,121"
      Width="NaN" Height="NaN" Name="button1">
      
                  Source="C:\Documents and Settings\Mark\
                 Desktop\banner.jpg"
          Name="image1"/>
                  Name="textbox1" Text="Type your name here!"
          Height="20" Width="333" />
                  Name="innerButton" Click="innerButton_Click">
          Press me!
       
      

   
 

Here is the code for the evenbubbing:

void button1_Click(object sender, RoutedEventArgs e)
{
  MessageBox.Show("Hello " + this.textbox1.Text);
  Button source = e.OriginalSource as Button;
  if (source != null)
  {
    MessageBox.Show(
      "The original source is: " + source.Name);
  }
}

void innerButton_Click(object sender, RoutedEventArgs e)
{
  MessageBox.Show("Hello Software Developer Network!");
}

This will look like:

Just click on the various controls. Notice that controls that do not have a 'Click' event do not participate in the routing, but may still pass the event on to their parent. In WPF this concept is called event routing. You can halt the routing of an event by setting the following code in one of the event handlers. This will stop the event from ‘bubbling’ further.

e.Halted = true;

The End?

This is all for now. I’ve only barely scratched the surface of all that WPF has to offer, but I hope this article will help create a basic insight in how the WPF user interface operates. Databinding is another area which I think is of particular interest. Keep an eye on my blog (http://blog.develop-one.com), I’ll make sure I post some material about databinding with WPF.

Geef feedback:
Verzend Commentaar