Archive for the ‘TrivadisContent’ Category

Take Snapshots PART II - Save as animated GIF

Wednesday, April 9th, 2008

I was asked, if it would be possible to save the snapshots created in my last post as an animated gif. With a DispatcherTimer and the GifBitmapEncoder-class you’re not far away from it. Just create a MediaElement in your Window:

<MediaElement Source="thomasOnBoard.wmv"
  x:Name="media" MediaOpened="media_MediaOpened"
  MediaEnded="media_MediaEnded" Width="300"
  Height="200" Stretch="Fill"/>

In the Codebehind-File, implement Eventhandlers for MediaOpened and MediaEnded-Events. In MediaOpened you start the DispatcherTimer. I’ve just used an interval of 100 milliseconds. In the Tick-Eventhandler, which is called each 100 milliseconds, a BitmapFrame is added to the GifBitmapEncoders Frames-Property. When the video ends, the MediaEnded-Eventhandler writes the GIF to your disk and opens the file. That’s it. :-)

public partial class Window1 : Window
{  …
  GifBitmapEncoder _encoder;
  DispatcherTimer _timer;
  private void media_MediaOpened(object sender, …)
  {
    _timer = new DispatcherTimer();
    _timer.Interval = TimeSpan.FromMilliseconds(100);
    _timer.Tick += OnTick;
    _timer.Start();
  }
  void OnTick(object sender, EventArgs e)
  {
    Size dpi = new Size(96, 96);
    RenderTargetBitmap bmp =
      new RenderTargetBitmap(300, 200,
        dpi.Width, dpi.Height, PixelFormats.Pbgra32);
    bmp.Render(media);

    if (_encoder == null)
      _encoder = new GifBitmapEncoder();

    _encoder.Frames.Add(BitmapFrame.Create(bmp));
  }

  private void media_MediaEnded(object sender, …)
  {
    _timer.Tick -= OnTick;
    _timer = null;

    string filename = Guid.NewGuid().ToString() + ".gif";
  FileStream fs = new FileStream(filename, FileMode.Create);
    _encoder.Save(fs);
    fs.Close();
    _encoder = null;

    Process.Start(filename);
  }
}

Here’s the gif saved from my video. Just click on it to see it animated:

withWPFCreated

Take Snapshots of Videos with WPF

Sunday, April 6th, 2008

With WPF’s Imaging-Classes you can take snapshots of any Visual. The snapshot can be saved in any common Image-Format, like e.g. JPG. Let’s take a look at a pretty short example, that shows how easy this can be done. The example takes snapshots of a Video.

The following Window contains a MediaElement and a Button. The MediaElement plays the Video thomasOnBoard.wmv. The Button defines an Eventhandler for the Click-Event. It takes a snapshot of the video, when you click it.

<Window x:Class="SnapShots.Window1"
    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/…
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
 ResizeMode="NoResize">
  <StackPanel>
   <MediaElement x:Name="media" Height="200" Stretch="Fill">
      <MediaElement.Triggers>
       <EventTrigger RoutedEvent="MediaElement.Loaded">
        <BeginStoryboard>
         <Storyboard>
          <MediaTimelineSource="thomasOnBoard.wmv"
           RepeatBehavior="Forever"/>
         </Storyboard>
        </BeginStoryboard>
       </EventTrigger>
      </MediaElement.Triggers>
     </MediaElement>
     <Button Click="Button_Click" Content="Snapshot"/>
  </StackPanel>
</Window>

Let’s look at the Eventhandler of the Button. An instance of the RenderTargetBitmap-class is created with some parameters about image-size, dots per inch (dpi) and Pixelformat. The Render-Method gets the MediaElement as a parameter, so MediaElements visual appearance is stored in the RenderTargetBitmap in memory. With a JpegBitmapEncoder and a FileStream the Image is written as a JPG to disk. That’s it.

void Button_Click(object sender, RoutedEventArgs e)
{
  Size dpi = new Size(96,96);
  RenderTargetBitmap bmp =
    new RenderTargetBitmap(300, 200,
      dpi.Width, dpi.Height, PixelFormats.Pbgra32);
  bmp.Render(media);

  JpegBitmapEncoder encoder = new JpegBitmapEncoder();
  encoder.Frames.Add(BitmapFrame.Create(bmp));

  string filename = Guid.NewGuid().ToString()+".jpg";
  FileStream fs = new FileStream(filename,FileMode.Create);
  encoder.Save(fs);
  fs.Close();

  Process.Start(filename);
}

Instead of taking the picture in the Button_Click eventhandler, you could create a Timer and take an Image every 0.1s. That allows you to extract an image-sequence of your videos. As it works for any Visual, and everything that’s on the screen in a WPF-Application is a visual, there are many things you can do with it. You could create a snapshot of an Image drawn to an inkCanvas, upload it to a webserver to display it on a webpage etc.

Dependency Properties - Value Precendence

Thursday, March 13th, 2008

The value of a Dependency Properties in WPF can be set from many sources: Templates, Styles, Data Binding, Animation, Local, Inherited from Element Tree,… That’s the reason why they are called "Dependency" Properties. Their values depend on many sources.

To get not a total chaos, there’s a precedence list in WPF that rules which value finally will be set. Here’s the list beginning with the source with lowest precedence (1.) up to the Source with highest precedence (10.):

  1. default-value
  2. Inherited Value
  3. Theme Style Setter
  4. Theme Style Trigger
  5. Style Setter
  6. Template Trigger
  7. Style Trigger
  8. Local Value
  9. Animated Value
  10. Coerced Value

WPF or better say its Property Engine calculates the value of a Dependency Property out of these sources. Finally the ValidateValueCallback checks if the value is valid (If a ValidateValueCallback was registered with the Dependency Property). If the value is not valid, the calculated-value wouldn’t be used (of course).

You have always to be aware of this precedence list, even in simple scenarios. Let’s take a short example. The Attached Property TextElement.Foreground has the Inherits-Flag set to true, so the value of this property is inherited through the element tree and you can set it on any element by using the attached property syntax, e.g. on a StackPanel like below:

<StackPanel TextElement.Foreground="Green">
    <TextBox>Should be green</TextBox>
    <TextBlock>Should also be green</TextBlock>
</StackPanel>

What do you think is the result of the codesnippet above? Do both, TextBox and TextBlock, display green text? I wouldn’t ask if they would do so. :-)

No, not both Elements display green text. The text inside the TextBox is still in the standard black or darkGray. The TextBlock displays its text in green.

Mhm… why doesn’t the TextBox inherit the Foreground-Value from the StackPanel? If you set the TextElement.Foreground-Property locally, it works, and the text inside the TextBox gets green:

<TextBox TextElement.Foreground="Green">
  Should be green
</TextBox>

So lets find out why the TextBox doesn’t get the inherited Value and displays its text still in standard color. Let’s take a look at the TextBox’s ControlTemplate defined in the Theme-Style for Vista’s Aero-Theme (the theme my PC is running on). In the Triggers-Section of the ControlTemplate a Trigger is defined that is actived when the IsEnabled-Property of the TextBox is true. You can see the Templates Trigger-Section below. And as you can see there, the Trigger sets the TextElement.Foreground-Property to the Brush stored in the Field SystemColors.GrayTextBrush (by using the GrayTextBrushKey-ResourceKey).

<ControlTemplate.Triggers>
  <Trigger Property="UIElement.IsEnabled">
    <Setter Property="Panel.Background" TargetName="Bd">
      <Setter.Value>
        <DynamicResource
     ResourceKey="{x:Static SystemColors.ControlBrushKey}"/>
      </Setter.Value>
    </Setter>
    <Setter Property="TextElement.Foreground">
      <Setter.Value>
        <DynamicResource
    ResourceKey="{x:Static SystemColors.GrayTextBrushKey}"/>
      </Setter.Value>
    </Setter>
    <Trigger.Value>
      <s:Boolean>False</s:Boolean>
    </Trigger.Value>
  </Trigger>
</ControlTemplate.Triggers>

If you look to the precedence-list at the beginning of this post, you see that the Inherited Value is on position 2., and the Template Trigger is on Position 6. So the Template Trigger has higher precedence. In the StackPanel with a TextBox and a TextBlock, the Template Trigger of the TextBox will set the foreground, and not the inherited value. When we set the local value, this local value is used, cause local value is on a higher position than the Template Trigger in the precedence list.

To go one step further, let’s override the Template of the TextBox and don’t set the TextElement.Foreground-Property in the Trigger-Section. As a result of the following code with the new TextBox-Template you’ll see that both, TextBox and TextBlock will display green text. :-)

<Window.Resources>
  <Style TargetType="TextBox">
  <Setter Property="Template">
   <Setter.Value>
    <ControlTemplate TargetType="TextBoxBase" …>
     <ScrollViewer Name="PART_ContentHost" …/>
    <ControlTemplate.Triggers>
     <Trigger Property="UIElement.IsEnabled">
      <Setter Property="TextElement.Foreground">
       <Setter.Value>
        <DynamicResource
  ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
       </Setter.Value>
      </Setter>
      <Trigger.Value>
       <s:Boolean>False</s:Boolean>
      </Trigger.Value>
     </Trigger>
    </ControlTemplate.Triggers>
   </ControlTemplate>
   </Setter.Value>
  </Setter>
 </Style>
</Window.Resources>
<StackPanel TextElement.Foreground="Green">
 <TextBox>Should be green</TextBox>
 <TextBlock>Should also be green</TextBlock>
</StackPanel>

Built-in DataGrid for WPF is planned

Saturday, February 23rd, 2008

Yes, they are planning to release it. Really great news. Today there’s no DataGrid for WPF-applications as part of .NET Framework 3.5. There are only third-party controls like the Grid from Xceed or Infragistics.

Have you ever built a business application without a DataGrid? I haven’t. I’m really happy to hear that microsoft will release a DataGrid for WPF as part of .NET. That wouldn’t make thirdparty-components necessary (If you don’t need all functionality e.g. Infragistics provides). I hope the DataGrid for WPF will be more like the DataGridView of WinForms in NET 2.0, and not like DataGrid in .NET < 2.0. :-)

Take a look at the .NET 3.5 roadmap on Scott Guthries blogpost. There’s a little line containing this information about a planned built-in DataGrid by end 2008. Also some other missing controls are planned, like Calendar/DatePicker.

Kick it like Beckham with WPF Animations

Thursday, February 21st, 2008

I’m just finishing the Animation-Chapter of my German-speaking WPF book (WPF-Buch erscheint im Juni 2008). I had a hard time to find a good idea how to show the reader animations in a really "non-boring", but easy way. And I think I’ve found one.

Animations in WPF are really powerful. You can create them completely in XAML. Even if the example of this post doesn’t make sense for a business application, think of the things you can do with animations:

  • Create buttons with professional hover-effekts
  • Improve the user-interface with some nice effects
  • Ease navigation for the user by animating something he should do now

Of course, Animations in business applications must be placed in the right way. It’s not recommended to animate everything you can. If you do so, your application won’t be serious anymore.

The application we are looking at here isn’t a business application. It’s just a small Loose XAML-File that allows you to become a soccer profi. :-) It show’s how animations are completely created in XAML and how they can be controlled.

Animations in XAML are placed inside Triggers. Either in an EventTriggers Action-Property or in another Triggers EnterAction or ExitAction-Property. These Properties are all of type TriggerAction. The BeginStoryboard-class and some other classes derive from TriggerAction. BeginStoryboard contains a Storyboard. The Storyboard itself contains the Animations.

Below a loose XAML. The Animation (bold) changes the Canvas.Top-Property of an image that contains a ball (the teamgeist-ball of worldcup 2006 Germany). The Animation starts, when a button with the Name btnStart is clicked. Between the ball-image the Canvas contains an image of me. And the clou is, it looks like I kick the ball for thousand times like a real profi.

<Grid Height="260" Width="300">
 <Grid.RowDefinitions>
  <RowDefinition/>
  <RowDefinition Height="Auto"/>
 </Grid.RowDefinitions>
 <Grid.Triggers>
  <EventTrigger RoutedEvent="Button.Click"
    SourceName="btnStart">
   <BeginStoryboard Name="beginStoryboard">
    <Storyboard TargetProperty="(Canvas.Top)"
      TargetName="imgBall">
     <DoubleAnimation AutoReverse="True" To="110"
     RepeatBehavior="Forever" Duration="0:0:0.25"
     AccelerationRatio="1"/>
    </Storyboard>
   </BeginStoryboard>
  </EventTrigger>
  <EventTrigger RoutedEvent="Button.Click"
    SourceName="btnStop">
   <StopStoryboard BeginStoryboardName="beginStoryboard"/>
  </EventTrigger>
  <EventTrigger RoutedEvent="Button.Click"
    SourceName="btnPause">
   <PauseStoryboard BeginStoryboardName="beginStoryboard"/>
  </EventTrigger>
  <EventTrigger RoutedEvent="Button.Click"
    SourceName="btnResume">
   <ResumeStoryboard BeginStoryboardName="beginStoryboard"/>
  </EventTrigger>
  <EventTrigger RoutedEvent="Button.Click"
    SourceName="btnSpeed2x">
   <SetStoryboardSpeedRatio SpeedRatio="2"
     BeginStoryboardName="beginStoryboard"/>
  </EventTrigger>
  <EventTrigger RoutedEvent="Button.Click"
    SourceName="btnSpeed1x">
   <SetStoryboardSpeedRatio SpeedRatio="1"
     BeginStoryboardName="beginStoryboard"/>
  </EventTrigger>
 </Grid.Triggers>
 <Canvas Width="250" Height="185">
  <Image Height="185" Source="fussballthomi.png"
    Canvas.Left="40"/>
  <Image x:Name="imgBall" Width="25" Canvas.Top="10"
    Canvas.Left="140" Source="teamgeist.png"/>
 </Canvas>
 <DockPanel Grid.Row="1" LastChildFill="False">
  <Button Margin="5" x:Name="btnStart" Content="Start"/>
  <Button Margin="5" x:Name="btnStop" Content="Stop"/>
  <Button Margin="5" x:Name="btnPause" Content="Pause"/>
  <Button Margin="5" x:Name="btnResume" Content="Weiter"/>
  <Button Margin="5" x:Name="btnSpeed1x" Content="1x"/>
  <Button Margin="5" x:Name="btnSpeed2x" Content="2x"/>
 </DockPanel>
</Grid>

Thomas kicks it like beckham. :-)

kickItXAML

More informations about my book, that contains the sample above and hundreds more (also more real world applications), you’ll find by march on www.thomasclaudiushuber.com

Bind to methods with ObjectDataProvider

Thursday, January 10th, 2008

Two classes inherit from DataSourceProvider. XmlDataProvider and ObjectDataProvider. ObjectDataProvider wraps an object and allows you to bind to the wrapped object in XAML. The ObjectDataProvider has a ConstructorParameters-Property for creating an object by using a constructor with parameters.

The cool thing is that a Data Binding to the wrapped object of the ObjectDataProvider is not all. With ObjectDataProvider you can even bind to a static method or to an instance method of the wrapped object. I’ll show you an example.

Just think about a really simple ComboBox that allows the user to chose some colors. Between the name of the color a rectangle filled with the color should be displayed (In WPF this is quite easy. You haven’t to create eventhandlers like you would do in Windows Forms. There you consumed the DrawItem-event of the ComboBox and used the Graphics-object to do a little bit of GDI+. In WPF GDI+ is gone). WPF’s Color class doesn’t have a name property. So just create a static class ColorHelper with one static method GetColorNames that returns an IEnumerable<string> and uses reflection to iterate over all public static properties of the Colors class that all contain Color-objects.

public static class ColorHelper
{
  public static IEnumerable<string> GetColorNames()
  {
    foreach (PropertyInfo p
      in typeof(Colors).GetProperties(
      BindingFlags.Public | BindingFlags.Static))
    {
      yield return p.Name;
    }
  }
}

The Window in the following XAML contains an ObjectDataProvider that uses the Static GetColorNames-Method of the ColorHelper class. The ItemsSource-Property (Typ: IEnumerable) of the ComboBox is bound to the ObjectDataProvider. The ItemTemplate-Property contains a DataTemplate that specifies the Visual Tree (the "look") of an item. Thanks to TypeConverters, a SolidColorBrush-Object is created for the Fill-Property of each Rectangle specified in the DataTemplate.

<Window    xmlns:local="clr-namespace:SimpleObjectDataProvider">
 <Window.Resources>
  <ObjectDataProvider x:Key="colors"
   ObjectType="{x:Type local:ColorHelper}"
   MethodName="GetColorNames"/>
 </Window.Resources>
 <StackPanel>
  <ComboBox
   ItemsSource="{Binding Source={StaticResource colors}}">
   <ComboBox.ItemTemplate>
    <DataTemplate>
     <StackPanel Margin="1" Orientation="Horizontal">
      <Rectangle Fill="{Binding}" Height="10" Width="10"
        Margin="2"/>
      <TextBlock Text="{Binding}" Margin="2 0 0 0"/>
     </StackPanel>
    </DataTemplate>
   </ComboBox.ItemTemplate>
  </ComboBox>
 </StackPanel>
</Window>

The displayed, open ComboBox looks like this:

comboBoxObjectDataProvider

Give your blog-code the "Visual Studio"-look

Monday, January 7th, 2008

How do you write a blog-entry with code that has the same syntax-highlightning like Visual Studio has? I mean this look:

<Code>
 <Code.Style>
  <Style TargetType="{x:Type Code}">
   <Setter Property="IsReallyGoodReadable" Value="Yes"/>
  </Style>
 </Code.Style>
</Code>

There are many different blug-ins. But only a few get the code exactly look like in Visual Studio. To get your code looking like the code above, you have to do 2 steps (with a small 3rd css-step):

1. Install Live Writer: http://get.live.com/WL/config_all - LiveWriter is a tool for writing blog entries offline

2. Go to the Live Gallery and download the "Paste from Visual Studio add in": Link to the Paste-Plugin

In LiveWriter you can paste the code direct from visual studio by clicking on the link of the plugin. After you’ve written your entry, you upload it, edit it online and finally publish it.

Special things for Firefox:

In Firefox the fontsize of the code is much smaller than in Internet Explorer 7. Fortunately the pasted code is inside a pre-Tag. The pre-Tags’ class-Attribut is set to "code". So you can easily point to the "code" in your css and give the font a fixed size, and it’ll look equal in Firefox and Internet Explorer.

3. The css-Step

I’ve set the fontsize in the css-File of my Wordpress theme to 10. The gray background of the code and the dotted border is also specified in my css.

Just past the following in your css to make the code exactly looking like the snippet above and the css-snippet itself:

.code
{
  font-family: Courier New;
  font-size: 10pt;
  background-color: #EEEEEE;
  margin: 0px;
  padding: 5px;
  border: dotted 1px #CCCCCC;
}

Tips: It’s a good practice to enter all linebreaks in Visual Studio before you paste the code into LiveWriter. I normally paste and delete and paste and delete and so on… until it fits. Find more tips on Karl Shifflets blog

Thanks to: Luca Bolognese and Charlie Calvert from Microsoft. They linked me to the plugin. Thanks also to Karl Shifflet who initiated this entry.

I hope this entry helps you to write your post with this format. How do you paste your code today? Do you know other plugins that give your blog-code the Visual Studio-look?

Working with the XmlDataProvider

Monday, January 7th, 2008

The XmlDataProvider class enables Binding to XML inside XAML. This will allow you to bind e.g. to the rss feed of a blog like http://www.thomasclaudiushuber.com/blog/feed/, cause rss is simple XML.

A XmlDataProvider-Element is declared as a logic resource. You simply set the Source-Property to a XML-Document and optionally set the XPath-Property. The default value of the IsAsynchronous-Property of the XmlDataProvider is true, so your client won’t freeze if you specify a url as the source.

The following XAML creates a simple rss-reader. The root is a Window object that contains a XmlDataProvider inside its Resources-Property. The XmlDataProvider loads the feed of this blog and its XPath-Property points to the blogs items. The elements inside the Window are indirectly bound to the XmlDataProvider. They use the DataContext specified on the DockPanel. The special thing of the Bindings on this elements is that they do not directly point to the XmlDataProvider. Instead the Bindings start at the /rss/channel/item like specified in the XPath-Property of the XmlDataProvider. If you want to point directly to the XmlDataProvider-object, you’ve to set the BindsDirectlyToSource-Property of the Binding to true. This is used by the first TextBox. It allows the user to change the Source-Property of the XmlDataProvider to navigate to another feed like http://blog.trivadis.com/blogs/MainFeed.aspx. The Binding for this TextBox also specifies that the UpdateSourceTrigger is PropertyChanged. Without this, the Source would be updated on LostFocus, cause the TextBox.TextProperty has specified this behaviour in its metadata.

<Window x:Class="SimpleRssReader.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/…"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="RSS Reader" Height="600" Width="800">
 <Window.Resources>
  <XmlDataProvider x:Key="blog"
   Source="http://www.thomasclaudiushuber.com/blog/feed/"
   XPath="/rss/channel/item"/>
 </Window.Resources>
 <DockPanel
   DataContext="{Binding Source={StaticResource blog}}">
  <StackPanel DockPanel.Dock="Top"
    TextElement.FontWeight="Bold" Background="LightGray">
   <TextBlock Text="{Binding XPath=./../title}"
     FontSize="20" Margin="10 10 10 0"/>
    <TextBlock Text="{Binding XPath=./../description}"
      FontSize="10" FontWeight="Normal" Margin="10 0"/>
   <TextBox Margin="5" Text="{Binding
     Source={StaticResource blog},
     BindsDirectlyToSource=True,
     Path=Source,
     UpdateSourceTrigger=PropertyChanged}"/>
 </StackPanel>

  <StatusBar DockPanel.Dock="Bottom">
   <StatusBarItem Content="{Binding XPath=title}"/>
   <Separator/>
   <StatusBarItem Content="{Binding XPath=pubDate}"/>
  </StatusBar>

  <Grid>
   <Grid.ColumnDefinitions>
    <ColumnDefinition Width="308"/>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition/>
   </Grid.ColumnDefinitions>

   <GroupBox Header="Blog-Eintr?ge">
    <ListBox IsSynchronizedWithCurrentItem="True"
      ItemsSource="{Binding}" DisplayMemberPath="title"/>
   </GroupBox>

   <GridSplitter Grid.Column="1"
     HorizontalAlignment="Center" Width="10"/>

   <Frame Grid.Column="2" Source="{Binding XPath=link}"/>
  </Grid>

 </DockPanel>
</Window>

To test the rss reader yourself, simply create a new WPF-Application Project and paste the XAML above into the Window1.xaml. You have just to set the value of the x:Class-Attribut on the Window-Element so that it matches your class in the Codebehind-File. The Codebehind-File itself doesn’t need any logic. The reader looks like this:

rssreader_XmlDataSource

C# 3.0 and WPF’s ListView

Wednesday, December 12th, 2007

In many applications you want to fill up a ListView or a GridView with some data. In WPF applications you set the View-Property of the ListView to a GridView to show the data nicely in columns. In most cases you have an entity class (think of it as a "real" entity class or a DataRow as part of a DataTable), and objects of this class should be represented in a row of the GridView. In WPF the DisplayMemberBinding-Property of each GridViewColumn is bound to a property of the entity class, so objects of the entity class can be easily added to the ListView and are displayed correctly in the GridViewColumns. But…

The problem (… the problem is more code as you want to have) begins, when you have no entity class and your data is stored in objects of different classes, maybe only in some variables, and you just want to display the data in one row of the ListView. If your variables have a relation to each other, it’s semantically correct to put them into one row of the ListView, displayed in different GridViewColumns. But to display the data in the ListView, you have to create a dummy entity class that contains your data. There’s no other way!

… no other way with C# 2.0. But now we have C# 3.0, and things can get much easier, cause the compiler can create nearly everything for you. :-) To show you how some C# 3.0 features can help you for the problem above with the dummy entity class, I have to step some months back in time and pick out a small sample that exactly shows the necessity of creating a dummy entity class.

Some months ago I created a small WPF application (.NET 3.0 and C# 2.0) to show developers how Routed Events are routed through the Element Tree. The application contains a Button and a ListView. The Button contains a StackPanel and inside this StackPanel is a Rectangle. Below the Window1.xaml:

<Window x:Class="RoutedEventsBeispiel.Window1"
xmlns=="http://schemas.microsoft.com/winfx/2006/xaml/.."
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="RoutedEventsBeispiel" Height="450" Width="500">
 <Grid>
  <Grid.RowDefinitions>
   <RowDefinition Height="Auto"/>
   <RowDefinition/>
  </Grid.RowDefinitions>
  <Button x:Name="button1" Width="100"
          Height="100" Margin="5">
   <StackPanel x:Name="stackPanel1" Background="Black">
    <Rectangle x:Name="rectangle1" Margin="10"
                 Fill="Red" Width="50" Height="50"/>
   </StackPanel>
  </Button>
  <ListView x:Name="listView" Grid.Row="1">
   <ListView.View>
    <GridView>
     <GridViewColumn Header="RoutedEvent"
       DisplayMemberBinding="{Binding RoutedEventName}"/>
     <GridViewColumn Header="Sender"
       DisplayMemberBinding="{Binding Sender}"/>
    </GridView>
   </ListView.View>
  </ListView>
 </Grid>
</Window>

Especially take a look at the DisplayMemberBinding-Property of the two GridViewColumns in the Window1.xaml above. To represent some data in this ListView, the Data must be represented by an object that has a Property RoutedEventName and a Property Sender. Therefore the Dummy class joins the game. Of course the class could be named in a better way like "RoutedEventInfo", but I decided to name it Dummy, because later with C# 3.0 this class won’t be necessary anymore:

public class Dummy
{
  private string _sender;
  private string _routedEventName;

  public string Sender
  {
    get { return _sender; }
    set { _sender = value; }
  }
  public string RoutedEventName
  {
    get { return _routedEventName; }
    set { _routedEventName = value; }
  }
}

In the constructor of Window1 in the codebehind Window1.xaml.cs a general Eventhandler for the Events UIElement.PreviewMouseLeftButtonDown and UIElement.MouseLeftButtonDown is added to the Window, the Button, the StackPanel and the Rectangle. The third parameter of the AddHandler-Method is always set to true. This true stands for "handledEventsToo", so the GeneralOnMouseDown-Eventhandler is called even if any EventHandler has set the Handled-Property of the RoutedEventArgs to true (That’s exactly what the ButtonBase class does internally with the MouseLeftButtonDown-Event, when the ButtonBase class raises its own Click-Event. So the third parameter is necessary here to get the application show the tunneling and bubbling of the events like expected)

public partial class Window1 : System.Windows.Window
{
  public Window1()
  {
   InitializeComponent();

   this.AddHandler(UIElement.PreviewMouseLeftButtonDown…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   this.AddHandler(UIElement.MouseLeftButtonDownEvent,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   button1.AddHandler(UIElement.PreviewMouseLeftButtonDown…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   button1.AddHandler(UIElement.MouseLeftButtonDown…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   stackPanel1.AddHandler(UIElement.PreviewMouseLe…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   stackPanel1.AddHandler(UIElement.MouseLeftButton…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   rectangle1.AddHandler(UIElement.PreviewMouseLeft…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   rectangle1.AddHandler(UIElement.MouseLeftButton…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
  }
void GeneralOnMouseDown(object sender,RoutedEventArgs e)
  {
   if (sender is Window1 
    && e.RoutedEvent==UIElement.PreviewMouseLeftButton…)
   {
     listView.Items.Clear();
   }
   Dummy d = new Dummy();
   d.Sender = sender.GetType().Name;
   d.RoutedEventName = e.RoutedEvent.Name;
   listView.Items.Add(d);
  }
}

The general Eventhandler GeneralOnMouseDown clears the Items of the ListView if the sender is a Window1 instance and the routed event is the tunneling event PreviewMouseLeftButtonDown. After that, it creates an instance of type Dummy, sets its Sender- and RoutedEventName-Property, and adds the Dummy instance to the ListView.

When you click on the red Rectangle located inside of the black StackPanel that is located inside of the Button, the ListView is filled up with Dummy objects, and it shows us, in which order the routed events are raised. The PreviewMouseLeftButtonDown-Events tunnels down from the Window1 to the Rectangle, then the MouseLeftButtonDown-Event bubbles up to the Window1.

20071118_RoutedEvents

That’s the application like I developed it with C# 2.0 and .NET 3.0. The need of the Dummy class is only necessary, because I got two string variables (the name of the routed event and the type name of the sender) that I have to put into one object, and this one object is put into the ListView. The GridViewColumns are bound to the Properties Sender and RoutedEventName of the object inside the ListView, so the Dummy objects are displayed like expected in the correct GridViewColumns.

Now how can I shorten my code with C# 3.0? We just focus on the GeneralOnMouseDown-Eventhandler and the Dummy-class. To add a Dummy object to the ListView, you can just use the Object Initializer to get it done in one instead of four statements:

listView.Items.Add(new Dummy() {
    Sender = sender.GetType().Name,
    RoutedEventName = e.RoutedEvent.Name });

Of course you could alternatively add a constructor to the Dummy-class instead of using an object initializer and you would reach a similar effect. But not always you’re the owner of such a Dummy-class and so you won’t be able to add a constructor. Even if you’re the owner of the Dummy-class, I think you like it to write less code (if you’re not paid per lines of code :-) ). With object initializers you won’t have to create many different constructors.

Now take a look at the Dummy class itself. It could be much shorter, if you use the Automation Properties of C# 3.0 (the IL-Code will still look the similar like before). With automation properties, the compiler creates the backing private fields for the specified properties:

public class Dummy
{
  public string Sender { get; set; }
  public string RoutedEventName{get;set;}
}

We can go even further.

If you’ve read the C# 3.0 specification, you’ve also read about Anonymous Types. So let’s go ahead one more step. Anonymous types are not only a feature that is good to use in LINQ-statements. In this small application here we could throw the Dummy class away and instead of Dummy objects we can add anonymous type objects to the ListView. The anonymous type must contain the properties Sender and RoutedEventName. So without the Dummy class you could fill up the ListView in the GeneralOnMouseDown-Eventhandler just with anonymous types like below, and the application still works the same way:

void GeneralOnMouseDown(object sender,RoutedEventArgs e)
{
  if (sender is Window1 && e.RoutedEvent==…)
    listView.Items.Clear();

  listView.Items.Add(new { Sender = sender.GetType().Name,
    RoutedEventName = e.RoutedEvent.Name });
}

In the background, the compiler creates an Anonymous class, that contains two properties Sender and RoutedEventName. So in IL you’ll find a class created from the anonymous type used above. But that’s not your problem, your C# Code itself gets much shorter.

The cool thing about C# 3.0 and Visual Studio 2008 is that you can use these C# 3.0 features to build .NET 2.0 applications (Of course for WPF applications you need at least version 3.0 of .NET). But be careful when using C# 3.0 features for .NET 2.0 apps. E.g. language enhancement features like LINQ are based on Extension Methods located in assemblies introduced with .NET 3.5. :-)

TechEd Developers 2007 in retrospect - Wednesday

Monday, November 26th, 2007

Wednesday at TechEd was another "linqy" day for me. In the morning I joined the session "LINQ to XML", with speaker Mike Taulty. With LINQ to XML there is a new XML-API as Part of .NET 3.5 which sits in the namespace System.Xml.Linq. LINQ to XML makes it easy to create and edit XML documents without using additional syntax like XPATH or XSLT, but, of course, LINQ to XML won’t replace the existing APIs implemented in classes like XmlDocument, XmlReader, XmlWriter or XPathNavigator. It’s just another XML-API that let’s you use LINQ queries on top of XML.

Mike Taulty showed that LINQ to XML is much closer to XML than the other XML-APIs as part of the .NET Framework. When you create a XML-document with the new API, you can see that your C#-Code is really close to the XML (if you format your code like below and additionally put the XAttribute-Elements on the same line as the XElements they belong to (I hadn’t enough space to do so :-))):

XDocument doc =
  new XDocument(
    new XElement("TrivadisLocations",
      new XElement("Location",
        new XAttribute("City","Basel"),
        new XElement("Consultants",
          new XElement("Consultant",
            new XAttribute("FirstName", "Thomas"),
            new XAttribute("LastName", "Huber")
          ),
          new XElement("Consultant",
            new XAttribute("FirstName", "Christoph"),
            new XAttribute("LastName", "Pletz")
          )
        )
      ),
      new XElement("Location",
        new XAttribute("City", "Freiburg"),
        new XElement("Consultants",
          new XElement("Consultant",
            new XAttribute("FirstName", "Thomas"),
            new XAttribute("LastName", "Wukasch")
          )
        )
      ),
      new XElement("Location",
        new XAttribute("City","Zürich"),
        new XElement("Consultants",
          new XElement("Consultant",
            new XAttribute("FirstName", "Patrick"),
            new XAttribute("LastName", "Spieler")
          )
        )
      )
    )
  );

doc.Save("locations.xml");

The XML generated from the code above looks like this:

<?xml version="1.0" encoding="utf-8"?>
<TrivadisLocations>
  <Location City="Basel">
    <Consultants>
      <Consultant FirstName="Thomas" LastName="Huber" />
      <Consultant FirstName="Christoph" LastName="Pletz" />
    </Consultants>
  </Location>
  <Location City="Freiburg">
    <Consultants>
      <Consultant FirstName="Thomas" LastName="Wukasch" />
    </Consultants>
  </Location>
  <Location City="Zürich">
    <Consultants>
      <Consultant FirstName="Patrick" LastName="Spieler" />
    </Consultants>
  </Location>
</TrivadisLocations>

OK, of course, writing XML is not such an amazing thing if you have a query language like LINQ. Reading XML would be more exciting. So let’s say you want to read the XML-file we’ve just created above and you want to get out each location-City where a "Thomas" works. You can just load the document by calling the static Load-Method of the XDocument-class and create a query on top of that document:

XDocument doc = XDocument.Load("locations.xml");

var query =
  from c in doc.Descendants("Consultant")
  where c.Attribute("FirstName").Value == "Thomas"
  select c.Ancestors("Location")
         .Attributes("City").First().Value;

foreach (string city in query)
{
  Console.WriteLine(city);
}

The Output on the Console is
> Basel
> Freiburg

With the query above you get the cities more than one time if there are more than one “Thomas” in one location. Fortunately the XML above has exactly one or none in each location. By using a simple group by you won’t get any cities more than one time, even if there are more than one “Thomas” in a location:

XDocument doc = XDocument.Load("locations.xml");

var query =
  from c in doc.Descendants("Consultant")
  where c.Attribute("FirstName").Value == "Thomas"
  group c
  by c.Ancestors("Location")
      .Attributes("City").First().Value
    into grouping
    select grouping.Key;

foreach (string city in query)
{
  Console.WriteLine(city);
}

In the afternoon I joined the Session "Entity Framwork: Application Patterns", with speaker Pablo Castro. If you’ve already had a look at the Entity Framework, maybe you were just thinking about the DataContext class. What is it with this class? Do you keep it in a stateful DataAccessLayer, or is it stateless and you create it each time the BusinessLayer accesses you DataAccessLayer? Pablo’s answer is that it’s stateless. The DataContext knows the structure and metadata of the underlying database, but it has no state and it is very thin. So in every method like "GetCustomerById(Guid customerID)", you would create a new instance of the DataContext. Normally you would create the DataContext in the header of a using-block, so that it’s automatically disposed at the end of that block.