WPF

 

Content

 

Intro

XAML

Layout

Dependency Properties

Routed Events

 

 

Intro

Intro

  • Windows Presentation Foundation (WPF)
  • Innovative graphical display system
    • Built-in hardware acceleration
    • Resolution independence
  • Targets
    • Win Vista, 7 and 8 Desktop Mode
  • Metro Toolkit
    • Limited to Win 8 only
  • Must target .NET 4

Evolution of Windows Graphics

  • Before WPF, same display tech for 15 years
  • User32
    • Traditional look and feel for elements like
    • windows, buttons, text boxes, etc.
  • GDI/GDI+
    • Drawing support
    • Render shapes, text and images 
  • Windows Forms, MFC
    • behind the scene User32 and GDI/GDI+ is used 

Evolution of Windows Graphics #2

  • Different frameworks are just  different wrappers
    • Performance improvements
    • Reduce complexity
    • Add prebaked features
  • But cannot remove fundamental limitations of User32 and GDI/GDI+

DirectX Graphics Engine

  • One way around limitations of User32 and GDI/GDI+
  • Mostly toolkit for game programming
  • Usually not used for GUI programming
  • Low level API
  • WPF uses DirectX as underlying graphics technology
  • Allows drawing buttons and complex 3D graphics
  • And effects and animations etc.
  • For certain services User32 is still used
    • Input and display management
    • Not for drawing

Hardware Acceleration and WPF

  • Most modern computers have very powerful graphics cards
  • WPF still provides software fallback
    • for legacy devices
    • but may be much slower

WPF API & Features

  • Web-like layout model
    • allows flow layout that arranges controls based on content 
  • Rich drawing model
    • Basic shapes, blocks of text and other graphical primitives
    • Transparent controls, multiple layers with varying opacities, native 3D support
  • Richt text model
  • Animations
    • Intrinsic part of framework, defined by declarative tags 

WPF API & Features #2

  • Audio & video support
    • Play multiple videos at the same time
  • Styles and templates
    • Standardize formatting and reuse
  • Commands
    • Define a single command and reuse it in several places
  • Declarative user interface
    • Either construct everything in code
    • Or set of XML tags (XAML document)
    • Separate user interface from code
  • Page-based applications
    • Browser-like apps
    • With forward / backward navigation

Resolution Independence

  • Usually developers assume standard monitor resolution
  • High resolution monitor - app looks smaller
  • E.g. 96 dpi, 120 dpi or retina display
  • WPF units
    • Measured in device-independent units

XAML

XAML Intro

  • Exensible Application Markup Language
  • Markup language used to instantiate .NET objects
  • Mostly used to construct WPF user interfaces
  • XAML defines
    • arrangement of panels
    • buttons
    • controls, etc.
  • Tools exist to create XAML
    • Visual Studio
    • Expression Blend
  • Better workflow for designers and developers

XAML Compilation

  • XAML solves problem of design collaboration
  • XAML is easy and flexible, but also needs to be fast
  • XML readable but not compact
  • BAML
    • Binary Application Markup Language
    • Binary representation of XAML
    • BAML is embedded as a resource in the final assembly
  • BAML is tokenized and optimized (shorter and faster)
  • Also possible to use uncompiled XAML
    • E.g.: Pulled out of DB as a block of XAML tags

XAML Basics

  • Every element in a XAML document maps to an instance of a .NET class
  • The name of the element matches the name of the class
  • XML allows nesting objects (Containers)
    • E.g. Button inside a Grid
  • Set properties of a class through attributes
    • Not always powerful enough
    • Nested tags with special syntax

XAML Basics #2

<Window x:Class="WpfBasics.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        
    </Grid>
</Window>
  • Blank window
  • Top-level window element
  • Grid as container
  • WPF top-level elements
    • Window
    • Page (navigable apps)
    • Application (define app resources and startup settings)

XAML Attributes

  • Window class properties
    • Device independent units
    • 300x300 pixel on a 96 dpi display
    • More pixels on a higher dpi display 
Title="MainWindow" Height="350" Width="525"

XAML Namespaces

x:Class="WpfBasics.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  • Class name and namespace is needed
  • Attribute used to define namespace
  • Namespaces may be defined on every element
  • But define all namespace on top-level element
  • xmlns reserved attribute used to define namespaces

XML Namespaces #2

  • http://schemas.microsoft.com/winfx/2006/xaml/presentation
    • core WPF namespace
    • here declared without namespace prefix
    • therefore default namespace for entire document
  • http://schemas.microsoft.com/winfx/2006/xaml
    • XAML namespace
    • Includes XAML utility features, allows you to influence how the document is interpreted
    • Mapped to prefix x
    • E.g.: <x:ElementName>

Code-Behind Class

// <Window x:Class="WpfBasics.MainWindow"></Window>

namespace WpfBasics {
    public partial class MainWindow : Window {
        public MainWindow() { InitializeComponent(); }
    }
}
  • x namespace prefix, places the Class attribute in the XAML namespace
  • Class attribute tells the XAML parser to generate a new class with specified name
  • That class is derived from the XML element (Window)
  • Supply partial class MainWindow, which is merged with the auto generated partial MainWindow class
  • Implement event handlers
  • InitializeComponent loads BAML and builds the user interface

Naming Elements

<Grid x:Name="MyGrid"></Grid>
// or
<Grid Name="MyGrid"></Grid>
  • Naming elements allows referencing controls in code

Type Converters

<TextBox Name="txtQuestion" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
FontFamily="Verdana" FontSize="24" Foreground="Green" ..> </TextBox>
  • Attributes of an element set the properties of the corresponding object
  • TextBox must provide all properties
  • Value of a XML property is always text
  • Object properties may hold any type
  • XAML parser performs conversion 
  • Given by type converters
    • converts to and from a .NET type
    • Here: string to .NET type

Type Converters #2

  • XAML parsers finds type converter in two steps
    • Examine property declaration, look for TypeConverter attribute
    • If no TypeConverter found, check class declaration of data type
      • E.g. Forground property uses Brush object
      • Brush class uses BrushConverter
  • If no TypeConverter is found, XAML parser generates an error

Complex Properties

<Grid x:Name="mainGrid">
    <Grid.Background>// ... </Grid.Background>
</Grid>
  • Some attributes are objects with own attributes
  • It is possible to use a string representation, but error prone and difficult to use
  • Property-element syntax
    • Parent.PropertyName
    • Grid has a Background property that allows to set a brush
    • For complex brushes use property-element syntax
  • (.) allows to distinguish between nested components and complex properties

Complex Properties #2

<Grid x:Name="mainGrid">
    <Grid.Background>
        <LinearGradientBrush>
            <LinearGradientBrush.GradientStops>
                <GradientStop Offset="0.00" Color="Red" />
                <GradientStop Offset="0.50" Color="Indigo" />
                <GradientStop Offset="1.00" Color="Violet" />
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
    </Grid.Background>
    // ...
</Grid>
  • Create nested element to define complex property
  • These may also have complex properties

Complex Properties #3

LinearGradientBrush brush = new LinearGradientBrush();

GradientStop gradientStop1 = new GradientStop();
gradientStop1.Offset = 0;
gradientStop1.Color = Colors.Red;
brush.GradientStops.Add(gradientStop1);

GradientStop gradientStop2 = new GradientStop();
gradientStop2.Offset = 0.5;
gradientStop2.Color = Colors.Indigo;
brush.GradientStops.Add(gradientStop2);

GradientStop gradientStop3 = new GradientStop();
gradientStop3.Offset = 1;
gradientStop3.Color = Colors.Violet;
brush.GradientStops.Add(gradientStop3);

mainGrid.Background = brush;
  • XAML tags may also be replaced with a set of code statements

Markup Extensions

<Button Foreground="{x:Static SystemColors.ActiveCaptionBrush}">
  • XAML property syntax not sufficient for all use cases
    • Set a property value to an object that already exists
    • Set property value dynamically 
    • Use markup extensions
  • Syntax: {MarkupExtensionClass Argument}
  • Here: StaticExtension class (drop Extension by convention)
  • All markup extensions derive from System.Windows.Markup.
    MarkupExtension.
  • XAML parser creates instance of StaticExtension passing SystemColors.ActiveCaptionBrush then calls ProvideValue()

Markup Extensions #2

<Button>
    <Button.Foreground>
        <x:Static Member="SystemColors.ActiveCaptionBrush"></x:Static>
    </Button.Foreground>
</Button>
  • StaticExtension is a class
  • Maybe used as complex attribute

Attached Properties

<Button Grid.Row=”1”>Ok</Button>
  • Properties that apply to several controls but are defined in a different class
  • Mostly used to control layout
  • When a control is nested in container it gains additional features depending on the container
  • E.g. Grid: choose grid cell for the current control
  • Syntax: DefiningType.PropertyName
  • Allows XAML parser to distinguish between attached property and normal property
  • Attached properties not real properties - they are translated into method calls: Grid.SetRow(btn, 1);

Events

// <Button Click="cmdAnswer_Click"></Button>

private void cmdAnswer_Click(object sender, RoutedEventArgs e)
{
    this.Cursor = Cursors.Wait;
    // Dramatic delay...
    System.Threading.Thread.Sleep(TimeSpan.FromSeconds(3));
    AnswerGenerator generator = new AnswerGenerator();
    txtAnswer.Text = generator.GetRandomAnswer(txtQuestion.Text);
    this.Cursor = null;
}
  • So far all attributes are mapped to object properties
  • Attributes can also be used for event handlers
  • Syntax: EventName="EventHandlerMethodName"

Layout

Intro

  • Coordinate-based layouts in the past
  • Possible in WPF but not common
  • Mostly weblike flow layouts
    • Show and hide content depending on screen size
    • Internationalization
  • In WPF there are different containers
  • Each container has its own logic

WPF Layout

  • Window can hold one single element
  • Add container and place all elements inside the container
  • Layout is defined by the container you use
  • Principles
    • Elements should not be exlicitely sized
    • Limit size by setting maximum or minimum sizes
    • Position not via screen coordinates
      • Arranged by container based on size, order and other info
      • Use margin for whitespace between elements
    • Containers share space among children
    • Containers can be nested

Layout Process

  • 2 stages: measure and arrange
  • Measure stage
    • Containers loops through child elements
    • Asks for preferred size
  • Arrange state
    • Container places the child in the appropriate position
  • Sometimes element do not get all the preferred size
  • Truncated to visible area

Layout Containers

  • All layout containers are panels that derive from System.Windows.Controls.Panel class
  • Panel class has three public properties
    • Background: Brush used to paint the panel background. Must be set to a non null value if moue events should be received (e.g. transparent)
    • Children: Collection of items stored in panel
    • IsItemsHost: True if the panel is being used to show items from an ItemControl 

Layout Containers #2

  • StackPanel
    • Places elements in a horizontal and vertical stack
  • WrapPanel
    • Places elements in a series of wrapped lines
    • In horizontal orientation WrapPanel lays items out in a row from left to right and then next line
    • In vertical orientation - top-to-bottom then next column 
  • DockPanel
    • Aligns elements against an entire edge of the container
  • Grid
    • Arrange elements in rows and columns
  • UniformGrid
    • Table layout, cells same size

Layout Containers #3

  • Canvas
    • Allows positioning via absolute coordinates 
    • Similar to Windows Forms
  • Several more specialized containers
    • ToolbarPanel, ToolbarOverflowPanel
    • VirtualizingStackPanel, etc.

StackPanel

  • Arrange elements from top to bottom
  • Each element as tall as necessary
  • Stretched to fill full width of StackPanel
  • Orientation="Horizontal"
    • Allows to specify the orientation
<Window x:Class="StackPanel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Label>Stack up buttons</Label>
        <Button>Test1</Button>
        <Button>Test2</Button>
        <Button>Test3</Button>
    </StackPanel>
</Window>

Layout Properties

  • Children of layout containers may specify needs via layout properties
  • HorizontalAlignment
    • Determines position of child element when there is extra horizontal space
  • VeritcalAlignment
    • Determine position when there is extra vertical space
  • Margin
    • Space around element
  • Width and Height
  • MinWidth/MinHeight and MaxWidth/MaxHeight
  • Inherited from FrameworkElement

Alignment

<Window x:Class="StackPanel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Label HorizontalAlignment="Center">Stack up buttons</Label>
        <Button HorizontalAlignment="Left">Test1</Button>
        <Button HorizontalAlignment="Center">Test2</Button>
        <Button HorizontalAlignment="Right">Test3</Button>
        <Button>Test4</Button>
   </StackPanel>
</Window>
  • Default value: Stretch

Margin

<Window x:Class="StackPanel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Label HorizontalAlignment="Center">Stack up buttons</Label>
        <Button HorizontalAlignment="Left" Margin="5">Test1</Button>
        <Button HorizontalAlignment="Center" Margin="2,5,2,5">Test2</Button>
        <Button HorizontalAlignment="Right">Test3</Button>
        <Button>Test4</Button>
   </StackPanel>
</Window>
  • Add spacing around element
  • Either single value or left, top, right, bottom

Dependency Properties

Intro

  • WPF replaces ordinary .NET properties with a higher-level dependency property feature
  • More efficient storage usage
  • Support change notification
  • And property value inheritance
    • Ability to propagate default values down the element tree
  • Basis for number of key WPF features
    • Animation
    • Data binding
    • Styles, etc.
  • Most of properties exposed by WPF elements are dependency properties

Defining Dependency Properties

public class FrameworkElement: UIElement, ... {
    public static readonly DependencyProperty MarginProperty;
    ...
}
  • Dependency properties can only be added to Dependency Objects
    • Classes that derive from DependencyObject
  • First define an object that represents the property
  • Is an instance of the DependencyProperty class
  • Must be static
    • Information about DP needs to be available all the time
    • Shared among classes
  • Field that defines DP has usual name + Property at the end
  • Must be readonly
    • Can only be set in the static constructor

Registering a Dependency Property

static FrameworkElement() {
    FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata(
    new Thickness(), FrameworkPropertyMetadataOptions.AffectsMeasure);
    MarginProperty = DependencyProperty.Register("Margin",
    typeof(Thickness), typeof(FrameworkElement), metadata,
    new ValidateValueCallback(FrameworkElement.IsMarginValid));
    ...
}
  • Two steps
    • Create FrameworkPropertyMetadata object to indicate what services you want to use with your dependency property (data binding, animation, and journaling)
    • Next register property by calling DependencyProperty.Register() method

Registering a Dependency Property #2

  • Need to supply few key properties
    • Property name (Margin)
    • Data type used by property (Thickness)
    • Type that owns this property (FrameworkElement)
    • FrameworkPropertyMetadata object with additional property settings (optional)
    • Callback that performs validation for the property (optional)
  • FrameworkPropertyMetadata mostly sets specific flags to provide additional information

Adding a Property Wrapper

public Thickness Margin
{
    set { SetValue(MarginProperty, value); }
    get { return (Thickness)GetValue(MarginProperty); }
}
  • Final step is to write a usual .NET property
  • Use SetValue and GetValue that are defined in the DependencyObject class
  • Do not write any other code in wrapper properties, since other features in WPF may bypass the property wrapper

Using Dependency Properties

#include <stdio.h>         // # marks a preprocessing directive 
  • Every DP supports change notification and dynamic value resolution
  • No events are fired, instead OnPropertyChangedCallback() is triggered
  •  

 

 

References

 

Pro WPF 4.5 in C# (4th Edition)

Matthew MacDonald

 

 

 

 

 

Thank you for your attention!

 

Made with Slides.com