Chicago WPF LOB Tour Materials (new materials added)

June 17, 2009

Chicago WPF LOB Tour attendees, thank you very much for sharing two wonderful days with Jaime and myself.  It was a real pleasure meeting you and diving into WPF together.  Wish you all great success in your careers.

Downloads

Slide Decks

Code and Demos

Note: The Code and Demos have been updated with new content.  Developers who attended a previous tour, may want to get the latest slides, code and demos.

Have a great day,

Just a grain of sand on the worlds beaches.


WPF – Float Buttons Over Web Browser Control

June 13, 2009

Kiosk

Above is a kiosk full screen capture.  Button panel is floating on top of the WebBrowser control. 

Introduction

We had just finished the Chicago WPF for Line of Business Training Tour and were having refreshments during which, the conversation somehow turned to the question, “how can I float buttons on top of the WebBrowser control?

It is a well know fact that WPF cannot render UIElements on top of the  WebBrowser control.  (see WPF Interoperation: Airspace and Window Regions Overview)

The developer I was speaking to had a WPF kiosk application that ran a combination of HTML and 3rd party Flash animations.  Since their application ran in a kiosk with smaller screens, they needed to be able to float WPF Button controls on top of the WebBrowser control as opposed to giving up some space on one of the edges for their buttons.

Karl being Karl, jump in with both feet and stated with authority, “of course you can do that.”  (Now I had to man-up and figure this out!)

After a few hours of developers talking shop, I headed up to the hotel room and wrote this application.

Application

The application consists of a single border-less, maximized Window.  The WebBrowser controls stretches to automatically consume all available screen space.

The below Button bar is a Border control that wraps the four buttons.  The buttons are all bound to commands that automatically take care of enabling and disabling the buttons.

Buttons

Notice that the Border is transparent  The blue border is just to show the outline for this article.  You can easily modify the layout of the Border’s contents.

You can also see when the application first loads, the Back and Forward buttons are disabled.  After the user navigates, the buttons will be enabled and disabled just like your Internet browsers are.  The Home button will take you to my blog, the Exit button will close the application.

<Grid>
  <WebBrowser x:Name="wbBrowser" />

  <Popup x:Name="puOverlay" AllowsTransparency="True" Placement="Bottom"
         PlacementTarget="{Binding ElementName=wbBrowser}">
    <Border x:Name="bdrOverLay" CornerRadius="30" BorderBrush="Blue"
            Background="#1F000000" Padding="7" BorderThickness="2">

      <StackPanel Orientation="Horizontal">
        <StackPanel.Resources>
          <Style TargetType="{x:Type Button}">
            <Setter Property="Width" Value="75" />
            <Setter Property="Margin" Value="3.5" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="HorizontalAlignment" Value="Center" />
          </Style>
        </StackPanel.Resources>
        <Button Command="NavigationCommands.BrowseBack" Content="Back" />
        <Button Command="NavigationCommands.BrowseForward" Content="Forward" />
        <Button Command="NavigationCommands.BrowseHome" Content="Home" />
        <Button Command="ApplicationCommands.Close" Content="Exit" />
      </StackPanel>

    </Border>
  </Popup>
</Grid>

The above XAML shows the WebBrowser and a single Popup control.  The Popup control will render on top of the WebBrowser control because it displays in its own Window.  Using some simple positioning code in the Window Loaded event, positions the Button bar centered at the bottom.  You can position the Button bar anywhere.

This application allows the kiosk user to interact with the web page and the Button bar using touch screen technology without giving up screen space along one of the edges.

Special Note

To the developers I was speaking to at the watering hole that night, I hope this meets your application requirements.

Download

After downloading you must change the file extension from .doc to .zip.  This is a requirement of WordPress.com

Source Code (25KB)

Have a great day,

Just a grain of sand on the worlds beaches.


WPF Sample Series – ListBox Grouping, Sorting, Subtotals and Collapsible Regions

June 10, 2009

This is the next sample in the WPF Sample Applications Series. The purpose of the Sample Series is to provide concise code solutions for specific programming tasks. This sample provides a brief description of the problem, the solution and full source code.

Introduction

These past few months I’ve been privileged to be a part of the WPF for Line of Business Training Tour.  What I really love is to be around developers excited about the WPF platform.  At each city I got requests from attendees to show them how to accomplish a task in WPF.  During a break I would sit down and write the code and usually I add the code to the session downloads.

This sample is the result of the question, “how can I do multi-level grouping?”

Application

All regions have been collapsed.  Count of Account Mangers is displayed along with the sales in dollars.

ListBoxOne

The West region has been expanded along with the child states.  Notice the state grouping level has totals for its state.  Account Manages have their name and sales figure displayed.

ListBoxTwoJPG 

Application Requirements

  • Grouping levels must be collapsible
  • Display total sales for Account Managers in the level
  • Display count of Account Managers in the level
  • Display the familiar “+” and “-” icon for expanding and collapsing levels
  • Sort data by region, state and sales descending

Grouping and Sorting

<CollectionViewSource Source="{x:Static local:Data.AccountManagers}" x:Key="cvs">
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="Region" />
        <scm:SortDescription PropertyName="State" />
        <scm:SortDescription PropertyName="Sales" Direction="Descending" />
    </CollectionViewSource.SortDescriptions>
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="Region" />
        <PropertyGroupDescription PropertyName="State" />
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

WPF provides the CollectionViewSource for codeless sorting and grouping of data.  The SortDescriptions and GroupDescriptions collections can be modified at runtime if desired.  The SortDescription provides the ability to set the sort direction as I’ve done for the Sales.

The ListBox consumes the CollectionViewSource data by assigning the ListBox.ItemsSource property to the CollectionViewSource resource.

Note:  I’ve assigned the Source to a static property so that I can have design time data and rending of the ListBox during development.

ListBox.GroupStyle

The ListBox.GroupStyle does all the heaving lifting for rendering the group level headers.  You have several options when working with GroupStyles. 

  • Define a GroupStyle.HeaderTemplate
  • Define a GroupStyle.ContainerStyle
  • Use a HeaderTemplateSelector to select the HeaderTemplate at runtime
  • Use a ContainerStyleSelector to select the ContainerStyle at runtime

For this application, I’ve chosen to define a ContainerStyle in XAML.

When defining a ContainerStyle, we will re-template the GroupItem that gets created for each level of grouping.

The purpose of re-templating the GroupItem is so that we have full control over how level is rendered.

<ListBox.GroupStyle>
  <GroupStyle>
    <GroupStyle.ContainerStyle>
      <Style TargetType="{x:Type GroupItem}">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="{x:Type GroupItem}">
              <ControlTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=IsBottomLevel}" Value="True">
                  <Setter TargetName="gridTemplate" Property="Grid.Background"
                          Value="#FF965F00" />
                </DataTrigger>
              </ControlTemplate.Triggers>
              <Grid>
                <Grid.RowDefinitions>
                  <RowDefinition />
                  <RowDefinition />
                </Grid.RowDefinitions>
                <Grid Background="Black" x:Name="gridTemplate" Height="26"
                      VerticalAlignment="Center">
                  <Grid.Resources>
                    <Style TargetType="{x:Type TextBlock}">
                      <Setter Property="FontSize" Value="14" />
                      <Setter Property="Foreground" Value="White" />
                      <Setter Property="VerticalAlignment" Value="Center" />
                    </Style>
                  </Grid.Resources>
                  <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="45" />
                    <ColumnDefinition Width="30" />
                    <ColumnDefinition Width="110" />
                  </Grid.ColumnDefinitions>

                  <ToggleButton x:Name="btnShowHide" IsChecked="True" Margin="3.5" />

                  <TextBlock Grid.Column="1" Text="{Binding Path=Name}" Margin="3.5,0" />
                  <TextBlock Grid.Column="2" Text="Count:" />
                  <TextBlock Grid.Column="3" Text="{Binding Path=ItemCount}"
                             TextAlignment="Right" Margin="0,0,11,0" />
                  <TextBlock Grid.Column="4"
                             Text="{Binding StringFormat=\{0:C\},
                            Converter={StaticResource groupItemSalesSubtotalConverter}}"
                             TextAlignment="Right" />
                </Grid>

                <ItemsPresenter
                  Visibility="{Binding ElementName=btnShowHide,
                                Path=IsChecked,
                                Converter={StaticResource booleanToVisibilityConverter}}"
                  Grid.Row="1" Margin="11,0,0,3.5" />

              </Grid>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </GroupStyle.ContainerStyle>
  </GroupStyle>
</ListBox.GroupStyle>

The DataContext for a GroupItem is a CollectionViewGroup.

In this ControlTemplate we will bind to the following properties of the CollectionViewGroup:

  • IsBottom – used by DataTrigger to set level heading Background
  • Name – used to display the level’s heading text
  • ItemCount – used to display the number of members in this level
Collapsible Group Levels

The ToggleButton has been re-templated to display an image that indicates the state of the Button.  (see download for template)

The ItemsPresenter at the bottom of the template is where the data items will be rendered. 

Using the built-in BooleanToVisibilityConvert and binding the ItemsPresenter.Visibility property to the ToggleButton.IsChecked property, we get simple, codeless collapse and expand behavior of the data members.

You really have to admire the sheer power of WPF here.

Subtotals

The last TextBlock Text property has a strange Binding.  There is no path.  When the converter is called, the DataContext will be passed as the value to the converter.  In this code the CollectionViewGroup will be passed to the converter.

Imports System.Windows.Data

<ValueConversion(GetType(CollectionViewGroup), GetType(Double))> _
Public Class GroupItemSalesSubtotalConverter
  Implements IValueConverter

  Public Function Convert( _
    ByVal value As Object, ByVal targetType As System.Type, _
    ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _
      As Object Implements System.Windows.Data.IValueConverter.Convert

    If value IsNot Nothing AndAlso TypeOf value Is CollectionViewGroup Then
      Return GetSubTotal(DirectCast(value, CollectionViewGroup))
    Else
      Return Nothing
    End If

  End Function

  Private Function GetSubTotal(ByVal obj As CollectionViewGroup) As Double

    Dim dbl As Double
    For Each objItem As Object In obj.Items
      If TypeOf objItem Is AccountManager Then
        dbl += DirectCast(objItem, AccountManager).Sales
      Else
        dbl += GetSubTotal(objItem)
      End If
    Next
    Return dbl
  End Function

  Public Function ConvertBack( _
    ByVal value As Object, ByVal targetType As System.Type, _
    ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _
      As Object Implements System.Windows.Data.IValueConverter.ConvertBack

    Throw New NotImplementedException

  End Function

End Class

This converter uses recursion to drill down to each member of the level and calculate a sales subtotal.

ListBox.ItemTemplate

<ListBox.ItemTemplate>
  <DataTemplate>
    <DockPanel>
      <TextBlock DockPanel.Dock="Right" HorizontalAlignment="Right"
                 Text="{Binding Path=Sales, StringFormat=C}" />

      <TextBlock Text="{Binding Path=FullName}" />

    </DockPanel>
  </DataTemplate>
</ListBox.ItemTemplate>

The ListBox.ItemTemplate is used when rendering the AccountManager data items.  A DockPanel provides the required layout.  The TextBlocks are data bound to properties on the AccountManager class.

Download

After downloading you must change the file extension from .doc to .zip.  This is a requirement of WordPress.com

Source Code (32KB)

Hope you can learn a little more about WPF from this article and the Sample Series.

Have a great day,

Just a grain of sand on the worlds beaches.


Phoenix WPF LOB Tour Materials (previous attendees this has new material)

June 10, 2009

Phoenix developers, thank you so very much for your hospitality and a wonderful time in your city.  Big time hats off to the Sheraton Four Points Phoenix North hotel too.  They gave us all 5 Star service.

Big thanks to Tim Heuer for organizing the Hawaiian shirt day on Friday!  Picture can be viewed here.

Downloads

Slide Decks

Code and Demos

Note: The Code and Demos have been updated with new content.  Developers who attended a previous tour, may want to get the latest slides, code and demos.

Looking forward to Chicago this Friday.

Have a great day,

Just a grain of sand on the worlds beaches.


Glimpse for Silverlight – Viewing Exceptions and Binding Errors

June 8, 2009

GlimpseOnLoad

Introduction

After my previous blog post, “Troubleshoot Silverlight 3 Data Bindings” I got some feedback and while in Phoenix I upgraded the code and have decided to call this Glimpse.

This initial release of Glimpse is a proof of concept project.  As I spend more time working with Silverlight 3, I’ll add more instrumentation views (Mole for Silverlight anyone?)

What is cool about Glimpse is that it can be used for local debug or deployed release builds.  It takes a single line of code to crank it up.

BTW:  I have not had a chance to make the UI pretty in Blend yet.  So go easy on Karl’s Moletones UI.

Glimpse Viewer Control

The Glimpse Viewer Control is hosted inside a Floatable WindowTim Heuer has a great post on how he modifed the default Silverlight ChildWindow so that it can be modal or non-modal.

I took Tim’s implementation and added the ability to set the location of the Floatable Window.  My code is in the Download section below.

Launching Glimpse

GlimpseLaunching

Glimpse is launched with a single line of code, passing the Application object and a string name for the Silverlight control.  If you have more that one Silverlight control on a web page, the name helps to know what control that Glimpse is providing information for.

In the above code, I’m testing if the current build is a DEBUG build. If so, launch Glimpse.  In your applications you can use other techniques for determining if Glimpse should be launched.

If your MainPage object throws an exception during object construction, Glimpse will display an Exception Viewer that will show you the exception and any inner exceptions.

To demonstrate this feature, you can uncomment the code in the MainPage constructor and then run the demo application.

GlimpseObjectConstructionException

Load Exception Viewer

The above code has outer and inner exceptions.  This viewer will display the outer exception and all nested inner exceptions.

GlimpseExceptionViewer

Application Unhandled Exceptions

When your Silverlight application has an application unhandled exception, the Glimpse Viewer Control will display a red ellipse on the right with a number indicating the number of unhandled exceptions.

  • Click the Expand button to display the Glimpse Viewer information
  • To return to contracted mode, click the Contract button
  • To clear the list of exceptions, click the Clear Exceptions button

GlimpseControlUnhandledExceptionNotification

GlimpseUnhandledException

Data Binding Exceptions

When your Silverlight application has an binding validation exception, the Glimpse Viewer Control will display a red ellipse on the left with a number indicating the number of exceptions.

In the below image, the Birthday field has text that can’t be converted into a date.

GlimpseDataBindingException

Pressing the Expand button displays the data binding validation exception.  This will also show any inner exceptions if they are present.

Notice the (Added) text on the left and field on the right.  This is the ValidationErrorEventAction property for the ValidationError.  When the validation error is cleared, the text will display “(Removed)”.

GlimpseDataBindingExceptionDetial

Bindings with no Source

The below image shows the Path with a typo, an “x” has been added to the correct property name “FirstName”.  This will cause a binding failure.

GlimpseNoBindingXAML

The below viewer provide information on all broken bindings in the host Silverlight control.  Binding errors are resolved each time the “Bindings with no Source” tab is selected.

GlimpseNoBindings

From Here

I have two projects that I want to launch on my blog, then I’ll take any feedback and add more views to the Glimpse Viewer Control.

What is nice about this approach is that you can launch Glimpse on a deployed production Silverlight control that needs some debugging love on a remote server in addition to using it during Silverlight control development.

Downloads

After downloading the below project, you must change the file extension from .doc to .zip, this is a requirement of WordPress.com.

Glimpse Control and Demo Project (61KB)

Karl’s Floatable Window  (22KB)

Have a great day,

Just a grain of sand on the worlds beaches.


Troubleshooting Silverlight 3 Broken Bindings

June 3, 2009

This post has been replaced by a much better approach.

Please view Glimpse for Silverlight – Viewing Exceptions and Binding Errors

Have a great day,

Just a grain of sand on the worlds beaches.


New York City WPF LOB Tour Downloads (new material)

June 1, 2009

Thank you New York City developers for spending two days with Jaime and myself.  I really enjoyed being in the “City” again and meet you all.

We have posted the slide decks, lab walk through, sample MVVM applications and class code at the following two links.

Slide Decks

Code and Demos

Note: The Code and Demos have been updated with new content.  Developers who attended a previous tour, may want to get the latest slides, code and demos.\

Looking forward to Phoenix and Chicago.

Have a great day,

Just a grain of sand on the worlds beaches.