Got the MCTS: .NET Framework 3.5, Windows Presentation Foundation

Last Thursday I took the exam for the Microsoft Certified Technology Specialist .NET Framework 3.5, Windows Presentation Foundation. The exam is brand new and covers a wide spectrum of WPF. Im not sure, if asking Multiple-choice-questions is a good thing for testing the knowledge of programmers, but hey, the exam was a good test for my German WPF-book. (I didn't have the book with me, but it's still in my head. Like a branding :-)). After every question I read, I thought, if the answer of the question can be found in my book. And I'm really glad to say that, with some exceptions to specific deployment questions, everything can be found in my book. So if you know all contents and details of my book well, you won't have any problems to pass this exam. So with the book still in my head I did it and earned my fourth MCTS:  MCTS_Logo By the way, I've finished the manuscript for my wpf book in time. Since end of April the correctors give their best and I'm sure the book will be in stores in June 2008, according to plan. Find more infos about the book-process during the next weeks on this blog.
Read more...

WPF Multi-Layer Business Application for Download

Tomorrow Karl Shifflett is giving a Code Camp session in Charlotte. Unfortunately it's too far away for me to participate. :-) Today Karl has posted a really great WPF Multi-Layer Business Application that can be downloaded from his blog. Check it out here and learn from it. Thx to Karl for posting and sharing that great sample app.
Read more...

LostFocus (TextBox) vs. Buttons IsDefault-Property

If you bind the Text-Property of a TextBox to something, the "something" is updated when the TextBox loses focus. This is the Default-UpdateSourceTrigger defined in the Metadata for the TextBox.TextProperty. In a Data Binding you can specify another UpdateSourceTrigger, like e.g. PropertyChanged. If a TextBox has LostFocus as UpdateSourceTrigger, which is the default, you can get problems if the TextBox is inside of a Dialog that contains a OK-Button with the IsDefault-Property set to true. When the TextBox has the Focus, the user can press Enter and the Button is clicked, but the TextBox still keeps the Focus. The LostFocus-Event doesn't occur, so the Source of a Data Binding isn't updated with the value of the TextBoxs Text-Property. You need to update the source explicit. Let's take an example and use the Person-class of my previous post:
public class Person : INotifyPropertyChanged
{
  private string _name;
  public string Name
  {
    get { return _name; }
    set
    {
      _name = value;
      if (PropertyChanged != null)
        PropertyChanged(this,
          new PropertyChangedEventArgs("Name"));
    }
  }
  public event PropertyChangedEventHandler PropertyChanged;
}
The Window below just contains a TextBox and a Button. The Text-Property of the TextBox is bound to the Name of the data in the DataContext. This would be a Person-instance, as you'll see below in the codebehind-file. The Button has it's IsDefault-Property set to true and defines an eventhandler for the Click-Event.
<Window x:Class="LostFocusTest.Window1" ...
  xmlns:local="clr-namespace:LostFocusTest"
  Title="Focus/IsDefault" Width="200" SizeToContent="Height">
  <StackPanel>
    <TextBox Margin="5" Text="{Binding Name}"/>
    <Button Content="OK" IsDefault="True"
       Click="Button_Click"/>
  </StackPanel>
</Window>
In the Constructor in the Codebehind-file a Person-instance is created. It's assigned to the Windows DataContext-Property, so the TextBox above will display the Persons name, which is set to "Thomas". The Click-Eventhandler for the Button simply displays the name of the Person in a MessageBox.
public partial class Window1 : Window
{
  private Person _pers;
  public Window1()
  {
    InitializeComponent();
    _pers = new Person();
    _pers.Name = "Thomas";
    this.DataContext = _pers;
  }

  private void Button_Click(object sender, RoutedEventArgs e)
  {
    MessageBox.Show(_pers.Name);
  }
}
If I start the application and type "Urs" into the TextBox and press Enter, the Button is clicked but the TextBox keeps the focus. So the Source, which is the Person-Instance, isn't updated and the MessageBox still displays the old value ("Thomas"), as you can see in the Image below: LostFocus vs. IsDefault For such a scenario, you have to update the source explicit. You could do this in the Click-Eventhandler. To update the source, you have to get the BindingExpression for the TextProperty. You get the BindingExpression by calling the GetBindingExpression-Method on the TextBox. Pass in the Text-Property as parameter. On the BindingExpression call the UpdateSource-Method to update the Person-instance explicitly with the value defined in the Text-Property of the TextBox. With the Eventhandler below the Person-Instance would always be actualized when the Button is clicked. The MessageBox would display the right value:
private void Button_Click(object sender, RoutedEventArgs e)
{
  TextBox textBox = Keyboard.FocusedElement as TextBox;
  if (textBox != null)
  {
    BindingExpression be =
      textBox.GetBindingExpression(TextBox.TextProperty);
    if (be != null)
      be.UpdateSource();
  }
  MessageBox.Show(_pers.Name);
}
Just kick it for me: kick it on DotNetKicks.com
Read more...

The dream of "half-automatic" Automation Properties

Everyone who has worked with WPF knows the interface INotifyPropertyChanged. It only defines the PropertyChanged-event, that should be called when a property's value has been changed. The PropertyChanged-event is used by WPF's Data Binding. Normally a class fires the event in the set-Accessors of its properties. And that's the problem why you can't use Automation Properties for classes that implement INotifyPropertyChanged. (more…)
Read more...

Take Snapshots of Videos with WPF

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>
          <MediaTimeline
Source="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.
Read more...

Built-in DataGrid for WPF is planned

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.
Read more...