#91 – What InitializeComponent() Does

The entry point into a WPF application, the Main function, is quite simple.  It creates an instance of your Application object, calls its InitializeComponent method and then its Run method.

The see the body of the Main function, as well as the body of InitializeComponent, do the following:

  • Build your application
  • Click on the Show All Files icon in the Solution Explorer

  • In Solution Explorer, navigate to App.g.cs file

Double-click to open App.g.cs.  You’ll see the body of Main.  You’ll also see the body of InitializeComponent.

public void InitializeComponent() {

    #line 4 "..\..\..\App.xaml"
    this.StartupUri = new System.Uri("MainWindow.xaml", System.UriKind.Relative);

    #line default
    #line hidden
 }

This function merely sets properties on the Application object based on values that you set in App.xaml.  By default, this includes only setting the StartupUri property to point to the application’s main window.

Update, 20-Oct-2010: InitializeComponent() does a bit more when generated for a Window, rather than for an App. See What Visual Studio Does with Your XAML for details.

#90 – Stepping Into .NET Source Code in Visual Studio 2010

It’s sometimes helpful to see not only the metadata for .NET and WPF classes, but to actually step through the source code in the debugger to see how things are working.

To enable stepping through .NET source code in the debugger:

First, close any open solutions.  Then, under Tools | Options, select Debugging | General and check the option Enable .NET Framework source stepping.

Also check the Enable Source Server Support checkbox. Next, select Debugging | Symbols in the list at left.  Unselect Microsoft Symbol Servers, if it’s checked.  Click on the add button and enter http://referencesource.microsoft.com/symbols.  Then click on the Empty Symbol Cache button.

When you start debugging, you’ll see a message indicating that symbols are being downloaded.  This may take some time.

When you first try stepping into a .NET Framework method, you’ll see a EULA.

But then you’ll find yourself looking at .NET source code.  Voila!

#87 – Type Converters

In XAML, you often set a property value by specifying a single string value.  However, when setting the value of a property that is not a System.String, the specified string must be converted into the proper type.  This is done automatically by the XAML parser using a type converter.

For example, in the example below, we set the background color of a button by specifying the string “Azure”.

 <Button Content="Click Me" Background="Azure" Height="25" Width="50" />

Because the Button.Background property is of type System.Windows.Media.Brush, the parser must convert the string “Azure” to a Brush object.

The XAML parser will attempt to convert the value if either:

  • The property in question has a TypeConverter attribute
  • The class that implements the property’s type has a TypeConverter attribute

For the Button.Background property, the value is converted from a string to a SolidColorBrush by the System.Windows.Media.BrushConverter class.

#86 – The Class Attribute Points to Your Code-Behind

The root element in a XAML file can have an x:Class attribute that specifies how to find the code-behind associated with the class being defined in the markup.

Examples:

 <Application x:Class="WpfApplication1.App"

or

 <Window x:Class="WpfApplication1.MainWindow"

When you build your project, the XAML is compiled and two things occur: 1) the XAML is converted into tokenized binary BAML; and 2) code is generated (e.g. C#) which will serve as a partial class that matches the partial class for your code-behind.  Notice that the value of the Class attribute matches the name of the corresponding class.

So in a default project, after building, you’ll get the following code files:

  • Main application
    • App.g.cs – code generated from App.xaml
    • App.xaml.cs – your code-behind for App class
  • Main window
    • MainWindow.g.cs – code generated from MainWindow.xaml
    • MainWindow.xaml.cs – your code-behind for MainWindow class

#85 – Two Main Namespaces Used in Every WPF XAML File

You’ll find the same two namespaces listed at the top of every .xaml file in a WPF project:

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

These namespaces correspond to two XAML vocabularies that define elements allowed in a WPF-based XAML file.

Although a URI is used to specify each namespace, they do not correspond to an actual web site.  The URI format is used to help ensure uniqueness across all organizations.

More information on these two namespaces :

#84 – Store Reusable Objects in a Resource Dictionary

Assume that you want to set the background color for two buttons to the same color.  You could specify a SolidColorBrush for each button’s Background property :

 <Button Name="btnOne" Content="Dum" Height="23" Width="75" Click="Button_Click">
     <Button.Background>
         <SolidColorBrush Color="AliceBlue"/>
     </Button.Background>
 </Button>
 <Button Name="btnTwo" Content="Dee" Height="23" Width="75" >
     <Button.Background>
         <SolidColorBrush Color="AliceBlue"/>
     </Button.Background>
 </Button>

In doing this, you created two different brushes.  But you could have been more efficient by creating a single brush, storing it in the resource dictionary of the parent window and then referencing the common brush when specifying the buttons’ Background property :

 <Window.Resources>
     <SolidColorBrush x:Key="aliceBrush" Color="AliceBlue"/>
 </Window.Resources>
 <StackPanel Name="spContainer">
     <Button Name="btnOne" Background="{StaticResource aliceBrush}" Content="Dum" Height="23" Width="75" Click="Button_Click" />
     <Button Name="btnTwo" Background="{StaticResource aliceBrush}" Content="Dee" Height="23" Width="75" />
 </StackPanel>

We created the common brush in the window’s resource dictionary–specified by the Resources property–and then referred to it in each Button using the StaticResource markup extension and a key.

#83 – Collection Syntax for Read-Only Vs. Read-Write Properties

When using the XAML collection syntax for a collection-based property that is read/write, the inclusion of an object element representing the collection object is optional.

E.g. Because FrameworkElement.Resources is read/write, we can list a series of resources using either of the following forms.

 <!-- Create new ResourceDictionary, assign to Resources property -->
 <Window.Resources>
     <ResourceDictionary>
         <SolidColorBrush x:Key="redBrush" Color="Red"/>
         <SolidColorBrush x:Key="indigoBrush" Color="Indigo"/>
     </ResourceDictionary>
 </Window.Resources>

 <!-- Omit ResourceDictionary, use collection syntax, new resources added to existing collection -->
 <Window.Resources>
     <SolidColorBrush x:Key="redBrush" Color="Red"/>
     <SolidColorBrush x:Key="indigoBrush" Color="Indigo"/>
 </Window.Resources>

However, for read-only collection properties, because you can’t create a new instance of the collection and assign it to the property, you must use the collection syntax, omitting the object element for the collection.

 <StackPanel.Children>
     <!-- Children property is read-only, so we can't include UIElementCollection element here -->
     <Button Content="Button" Height="25" Width="50" />
<ComboBox Height="23" Width="120" />
 </StackPanel.Children>

#82 – How XAML Handles Whitespace

In general, embedded spaces and line feeds in a XAML file are ignored.  You can normally include spaces or line feeds between consecutive items.  Here are some guidelines:

  • You must have at least one space preceding each XAML attribute
  • You must not have any whitespace following the open angle bracket ‘<‘ in an element tag
  • You must not have any whitespace between the ‘/’ and ‘>’ characters in a self-closing element
  • Whereever a namespace prefix is used, with the ‘:’ character, you must not have whitespace on either side of the ‘:’
  • When a property value is expressed as text within quotation marks and it represents textual content, embedded whitespaces and line feeds are preserved.  (E.g. Embedded line feed in a button label)
  • When text is used as a value for a content property, i.e. not in quotation marks
    • All leading and trailing whitespace is removed  (i.e. the string starts with the first non-whitespace character)
    • Internal whitespace is converted to a single space