Properties and More in XAML

In this third part of a three-part series covering the basics of XAML, you will learn about attached properties, binding properties, and more. It is excerpted from the book XAML in a Nutshell, written by Lori A. MacVittie (O'Reilly, 2006; ISBN: 596526733). Copyright © 2006 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.

Contributed by
Rating: 4 stars4 stars4 stars4 stars4 stars / 3
April 12, 2007
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

Abbreviated Syntax

Abbreviated syntax must sound like jabberwocky at this point, but it’s really a pretty neat concept. It uses a predefined format, such as CSV (comma-separated values), to essentially declare the arguments that will be passed to the appropriate class constructor beneath the covers. You can think of the String definition as the list of arguments you’d normally pass to a constructor, except that sometimes you don’t need a comma to separate the arguments.

Example 3-11 first creates an EllipseGeometry in C# and then assigns a Point to be its Center property by instantiating a new Point and passing the appropriate values to its constructor. The XAML code in the same example creates an EllipseGeometry and then assigns a Point to be its Center attribute using abbrevi ated syntax. The 0.5, 0.5 is parsed by the WPF engine, and the values are passed to a Point constructor as its arguments.

Example 3-11. Abbreviated syntax and arguments in C#

C #
EllipseGeometry ellipse;
ellipse.Center=new Point(0.5, 0.5);

XAML
<EllipseGeometry
   
Center="0.5,0.5" />

A very common example of using abbreviated syntax to declare attribute values is the assignment of predefined color names to an attribute declared as type Brush , such as the Background attribute. Rather than forcing you to go through all the typing required to explicitly declare a Brush and set its color, XAML allows you to just declare the attribute as Red or Green instead.

Figure 3-3 shows the result of declaring a Red SolidColorBrush as the background Brush for a Button using both abbreviated markup and by explicitly declaring the complex attribute. Example 3-12 shows the code used to declare both elements.


Figure 3-3.   Result of explicit declaration and abbreviated markup declaration of a Brush attribute on a Button

Example 3-12. Explicit declaration of a Brush versus abbreviated markup

<StackPanel
    xmlns=http://schemas.microsoft.com/ winfx/avalon/2005
    Margin="10 10 10 10">
    <Button
       
Width="350"
        Height="30"
        Content="Button with explicitly declared Background Brush">
        <Button.Background>

            <SolidColorBrush Color="Red" />
       
</Button.Background>
    </Button>
    <Button
        Width="350"
        Height="30"
        Background="Red"
        Content="Button with a Background Brush declared using abbreviate
               
markup"/>
</StackPanel>

As you can see in Figure 3-3, both buttons are painted with the same back ground, regardless of the method used to declare the Brush . Abbreviated syntax is typically used because it requires less typing. There are no advantages to using explicit syntax in most cases where abbreviated syntax is available, and it’s less typing for you.

A more complex example is the common use of abbreviated markup syntax to declare elements of the type Point . Point is a common, complex attribute that is used in the declaration of almost every geometric XAML element. You can use the abbreviated markup syntax for a Point element wherever an element of type Point is declared. You’ll notice in Example 3-13 that EllipseGeometry has several attributes. While RadiusX and RadiusY are Double values, the Center attribute for an EllipseGeometry is actually a complex attribute of type Point . In its abbreviated syntax, Point accepts two comma-separated values representing the X and Y positions, respectively. Example 3-13 shows different ways of using Point (in this case, it is used through the Center attribute).

Example 3-13. Example of abbreviated markup versus explicit syntax

<GeometryGroup>
   
<EllipseGeometr y
        RadiusX="0.45"
        RadiusY="0.2"
        Center="0.5,0.5" />

    <EllipseGeometry
        RadiusX="0.2"
        RadiusY="0.45">  
        <EllipseGeometry.Center>
            <Point
                X="0.5"
                Y="0.5" />

        </EllipseGeometry.Center>
     </EllipseGeometry>
</GeometryGroup>

Elements that can be declared using abbreviated markup syntax are specifically noted in Part III.

Attached Properties

A few XAML elements have attributes that are declared in other elements rather than in the element itself. These attributes are called attached properties. Attached properties are generally used to position elements within a parent element. Two elements with attached properties are Grid and DockPanel . Grid uses attached properties to describe the row and column in which an element should be contained. DockPanel uses attached properties to describe the location within the panel where an element should be placed.

Attached properties can be set on any element that derives from DependencyObject . UIElement derives from DependencyObject , so the requirement is met by most XAML elements.

Attached properties are declared in an element by using a reference to the element and the attribute being declared in the following manner: AttachPropertyProvider.PropertyName . For example, Grid has two attached properties: Row and Column . An element contained within a specific row/column combination in a grid would specify the row as an attribute with the name Grid.Row and the column similarly as Grid.Column . Example 3-14 describes the use of these attached properties.

Example 3-14. Using the attached properties of Grid

<Grid
    ShowGridLines="true">
    <ColumnDefinition
        
Width="50"/>
    <ColumnDefinition
         Width="50"/>
    <RowDefinition
         Height="100" />
    <RowDefinition
         Height="25" />
    <RowDefinition
         Height="25" />
    <TextBlock
        
Grid.Column="0"
         Grid.Row="0">Col 0, Row 0
    </TextBlock>
    <TextBlock
        
Grid.Column="1"
       
Grid.Row="0">Col 1, Row 0 
    </TextBlock>
   
<TextBlock
        
Grid.Column="0"
         Grid.Row="1">Col 0, Row 1
   
</TextBlock>
   
<TextBlock
        
Grid.Column="1"
       
Grid.Row="1">Col 1, Row 1  
    </TextBlock>
</Grid>

Binding Properties

Another mechanism in XAML that can be used to declare the value of attributes is a bind declaration. A bind declaration allows you to set an attribute’s value by referencing the value of another element. Bind declarations must be attached to a specific dependency property of a target element. Remember that dependency properties are static read-only properties of a CLR class that are exposed only through get and set accessor methods to support concepts such as binding. Prop erties are bound together in a bind declaration using the Binding element.

Binding elements are used to bind the source to target elements. If the dependency properties in the source elements change when the application runs, the dependency properties in the target elements will change as well. Basically, you’re telling an attribute that its value should always be determined by evaluating some other attribute or data source. It’s like assigning a value to one variable by assigning it to another, as shown in the following example:

  int a = 1;
 
int b;
 
b = a;

The difference between code-based variable assignments and XAML binding is that in XAML, the association is permanent. The assignment of b=a in the code example happens only once, and, if a changes later, b doesn’t follow suit. In XAML, the Binding keyword ties the values together permanently.

The syntax for a Binding element is as follows:

  <ElementName Attribute="{Binding Path=SimpleProperty, Mode=OneTime} />

The curly braces are a general indicator to the parser that the value contained in the braces is not a simple value. Instead, the first keyword within the braces indicates the type of special handling needed. The Binding statement at the beginning of the string indicates a binding declaration.

An example of how binding works is when you are tying together the content of two different elements, such as a Button and a TextBlock . In Example 3-15, every time the Button is clicked, the C# code (Example 3-16) in its codebehind handler will increment a static counter and change the content of the Button to include that count. The TextBlock will bind its own content attribute to the content attribute of the Button , so every time the Button is clicked, it too will change its content—automagically through the use of the Binding element.

Example 3-15. Binding attributes: XAML

<Page 
    xmlns=http://schemas.microsoft.com/ winfx/avalon/2005
    xmlns:x=http://schemas.microsoft.com/ winfx/xaml/2005
    x:Class="BindExample.Page1">
    <StackPanel >
        <Button
            Width="150"
            Content="You have clicked 0 times!"
            Name="MyButton"
            Click="ButtonClicked"/>

        <TextBlock>
            <TextBlock.TextContent>

                <Binding
                    ElementName="MyButton"
                    Path="Content"/>
            </TextBlock.TextContent>
        </TextBlock>
    </StackPanel>
</Page>

Example 3-16. Binding attributes: C#

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using System.ComponentModel;

namespace BindExample
{
    public partial class Page1 : Page
    {
       
static int clickCount = 0;
        void ButtonClicked(object sender, RoutedEventArgs e)
        {
          
MyButton.Content="You have clicked " + ++clickCount + " times!";
        }
    }
}

After compiling the application and running it, the content of MyButton is appro priately, “You have clicked 0 times!” (Figure 3-4).

Clicking on the Button executes the ButtonClicked handler detailed in Example 3-16. The counter increments and the Content of the Button is changed to include the count. Notice that nowhere in the code do you touch the TextBlock declared in Example 3-15. The Content of that TextBlock is bound to the Button ’s Content attribute by the Binding element, and whenever it changes, so will the content of the TextBlock . Clicking on the Button a few more times results in Figure 3-5.

You might think that this isn’t very useful. Binding content attributes of one element to another isn’t something you’ll do very often, but the Binding element


Figure 3-4.  Binding example on initial run


Figure 3-5.  Binding example after a few clicks

can also be used for more common scenarios, such as binding a ListBox to an XML data source and then binding the attribute of a TextBlock to the selected value in the ListBox . Example 3-17 demonstrates binding an element to an XML data source.

Example 3-17. Binding to an XML data source

<Page xmlns=http://schemas.microsoft.com/winfx/ avalon/2005 
      xmlns:x="http://schemas.microsoft. com/winfx/xaml/2005">
   
<StackPanel >
        <StackPanel.Resources>
        <XmlDataSource
           
x:Key="UserData"
            XPath="/Users">
            <Users xmlns="">
                <User ID="1">
                    <Title>CEO</Title>
                    <Name>Elisabeth</Name>
                </User>
               
<User ID="2">
                    <Title>CTO</Title>
                    <Name>Galina</Name>

                </User>
               
<User ID="3">
                    <Title>CSO</Title>
                    <Name>Donald</Name>
                </User>
               
<User ID="4">
                    <Title>CFO</Title>
                    <Name>Victoria</Name>
                </User>
               
<User ID="5"> 
                    <Title>CIO</Title>
                    <Name>Korey</Name>

                </User>
            </Users>
            </XmlDataSource>
            <DataTemplate x:Key="UserDataTemplate">
                
<TextBlock FontSize="Small" Foreground="Red">
                    <TextBlock.TextContent>
                       <Binding XPath="Title"/>
                   </TextBlock.TextContent>
                </TextBlock> 
           </DataTemplate>
       </StackPanel.Resources>
     
<ListBox
          HorizontalAlignment="Left"
          Margin="10"
          Width="100"
          Height="100"
          Name="MyListBox"
          SelectedValuePath="Name"
          ItemsSource="{Binding Source={StaticResource UserData}, XPath=User}"
          ItemTemplate="{StaticResource UserDataTemplate}"/>
      
<TextBlock
          HorizontalAlignment="Left"
          Margin="10">
          <TextBlock.TextContent>
              <Binding ElementName="MyListBox" Path="SelectedValue" />
          </TextBlock.TextContent>
      </TextBlock>
    </StackPanel>
</Page>

In Example 3-17, there are three uses of the Binding element. It is first used as the value of the ListBox ’s ItemsSource attribute. This declaration tells the ListBox that it should get its items from the StaticResource UserData and to use the XPath User  to determine what an item consists of. The second use of the Binding element, the ItemTemplate value, tells the ListBox how to display the data. The UserDataTemplate tells the ListBox that each item should be displayed as a text block with a small, red font and that the value shown is the User attribute Title  (specified by the XPath="Title" declaration).

The final use of the Binding attribute appears within the TextBlock declaration. It binds the content of the TextBlock to the SelectedValue attribute of MyListBox . The great thing about this particular use of the Binding attribute is that there’s no code necessary. When a User is selected from the ListBox , the TextBlock Content will automatically update to reflect that user’s Name (Figure 3-6). The SelectedValuePath in the ListBox determines what value is displayed in the TextBlock when the
selec tion changes.


Figure 3-6.  Result of evaluating Example 3-17 in
XamlPad

Basically, the ability to bind the attributes of an element to other elements and even data sources provides a non-coding method of manipulating data and display.

Codebehind

The concept of codebehind has been mentioned but not fully explored yet. You’ve already noted that event handlers can be assigned to elements and implemented in code and that the attribute name must exactly match the handler name in code. The event handlers specified by name as attributes for controls are associated with the codebehind in a C# or VB.NET file during the compilation process. The compiler generates a partial class for XAML and then assembles it with the code, which defines the rest of the class in a codebehind file. This allows the two pieces to be tied together when the code is interpreted within the runtime engine.

But there are other things that can be accomplished in code besides handling events. Many applications require initialization of data sources, or automatically adding fields to the user interface depending on the user’s role. These things cannot be done in XAML; they must be done programmatically.

Every XAML application represents the declaration of a partial CLR class. Part of the class is declared using XAML, and the rest of it can be declared in a codebehind file using C# or Visual Basic. The implementation can then programmatically modify the user interface or interact with other systems such as a database or remote application to accomplish the application’s designated task.

As with event handlers, the name of the class assigned as the implementation class for a XAML application must exactly match, including the namespace. For example, the XAML class declaration in Example 3-18 referencing the StartPage class with a namespace of MyNameSpace exactly matches the name of the class in Example 3-19. Note that the Page element in the XAML file has no other elements. The TextBlock and Button seen in Figure 3-7 are the result of programmatically adding the two elements to the Page in the C# codebehind implementation.

Example 3-18. XAML declaration of StartPage.xaml

<Page xmlns=http://schemas.microsoft.com/ winfx/avalon/2005
      xmlns:x=http://schemas.microsoft. com/winfx/xaml/2005
      x
:Class="MyNameSpace.StartPage"
      Loaded="Init" />

Example 3-19. C# implementation of StartPage class within StartPage.xaml.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace MyNameSpace
{
   public partial class StartPage : Page
   {
      
TextBlock txtElement ;
       StackPanel rootPanel;
       Button aButton;
       void Init(object sender, EventArgs args)
       {
                
rootPanel = new StackPanel();
                 txtElement = new TextBlock();
                 aButton = new Button();
                 txtElement.TextContent = "Some Text";
                 aButton.Content = "Press me";
                 Child = rootPanel;
                 rootPanel.Children.Add(txtElement);
                 rootPanel.Children.Add(aButton);
      
}
   }
}

In Example 3-19, you can see that a StackPanel is declared as rootPanel , indi cating that it will be the first (and only) child of Page . Page is only allowed a single child of type UIElement , so all other elements to be displayed on the page will have to be added to the StackPanel . The C# code in this example is equivalent to the XAML code in Example 3-20.


Figure 3-7.  Programmatic creation of a XAML application

Example 3-20. XAML declaration to produce Figure 3-7

<Page xmlns=http://schemas.microsoft.com/winfx/ avalon/2005
      xmlns:x=http://schemas.microsoft. com/winfx/xaml/2005 >
   
<StackPanel>
       
<TextBlock>Some Text</TextBlock>
       
<Button Content="Press me" />
   
</StackPanel>
</Page>

If it can be done in XAML, it can be done programmatically. Every XAML element is accessible from C# or Visual Basic and can be manipulated within event handlers or from within the class’s implementation. This provides you with the means to add or remove elements from the user interface, allows for localization, and offers the ability to dynamically build a user interface based on data-driven principles.

While XAML was designed to separate the presentation layer from the application logic, its representative CLR classes are available to the programmer and can be used to build an application in the same way traditional Windows Forms or .NET applications are built.

blog comments powered by Disqus
XML ARTICLES

- More on Triggers and Styles and Control Temp...
- Looking at Triggers with Styles and Control ...
- A Closer Look at Styles and Control Templates
- Styles and Control Templates
- Properties and More in XAML
- Elements and Attributes in XAML
- XAML in a Nutshell
- Importing XML Files into Access 2007
- Using MSXML3.0 with VB 6.0
- MSXML, concluded
- MSXML, continued
- MSXML Tutorial
- Generating XML Schema Dynamically Using VB.N...
- XSL Transformations using ASP.NET
- Applying XSLT to XML Using ASP.NET

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 6 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials