Archive

Archive for the ‘Uncategorized’ Category

WPF NotifyIcon – Bugfix and WinForms Support

September 22nd, 2009

I released an update to my WPF NotifyIcon, which fixes two issues:

  • Interactive Popups should now fully support all control types.
  • The control can now be used in Windows Forms projects, if you need more functionality than the built-in component.

The solution now comes with an additional WinForms sample project, which shows how to display a WPF user control as an interactive popup.

image

     

    Download link and further information can be found on the control’s home page:
    http://www.hardcodet.net/wpf-notifyicon

    Tags:

    Twitter Debut

    May 5th, 2009

    imageI’ve been somewhat hesitant, but being able to quickly exchange thoughts with the community just sounds too good – I have to try this out.

     

    Follow me @ http://twitter.com/phsumi

    Tags:

    From Lambda Dependencies to Lambda Bindings

    April 3rd, 2009

    Lambda-based binding for the business layer or your View Model :)

    I’ve had this on the shelf for quite a while, but Kent Boogaart’s article on POCOs vs. DependencyObjects finally got me to cleaning things up a little. Kent is coming up with a similar approach that looks very promising, so you should keep your eyes on his blog, too.

    Lambda Bindings are built on top of the Lambda Dependencies project I published a while ago. The original Lambda Dependencies allow you to observe object graphs for changes using simple LINQ expressions. Lambda Bindings leverage this pattern by not just publishing a change event but synchronizing target properties or fields automatically.

    This provides you with a generic binding framework that can be used wherever you want to synchronize objects. Let’s have a first example:

     

    public void TestBinding(Student student)
    {
      string cityName = "";
    
      //synchronize the cityName field with the City property of the school's address
      var binding = LambdaBinding.BindOneWay(
          () => student.School.Address.City,
          () => cityName);
    
      //change the property on the School object
      student.School.Address.City = "Sin City";
    
      //the binding expression updated the local variable
      Assert.AreEqual("Sin City", cityName);
    }

    What’s happening in the snippet above is that I created a binding between a nested property of a referenced object and a local field. As soon as the binding source (the City property of a school’s address) is changed, the local cityName field is being updated as well.

     

    However, the Lambda Dependencies not only cover the source properties but the whole object graph. Accordingly, exchanging the whole School (or the Student instance) also triggers an update. In the snippet below, the cityName variable is being updated twice:

     

    [Test]
    public void Updating_Intermediary_Object_Should_Update_Target(Student student)
    {
      string cityName = "";
    
      //synchronize the cityName field with the City property of the school's address
      var binding = LambdaBinding.BindOneWay(
          () => student.School.Address.City,
          () => cityName);
    
      //change bound City property -> triggers update of the local variable
      student.School.Address.City = "Paris";
      Assert.AreEqual("Paris", cityName);
    
      //create a completely different school instance
      School englishSchool = new School();
      englishSchool.Address = new Address {City = "London"};
    
      //assign the new school to the student
      student.School = englishSchool;
    
      //setting the School property also triggered the binding
      Assert.AreEqual("London", cityName);
    }

     

    Value Conversion

    You can do simple value conversion by just submitting a converter to the binding expression. This allows you to intercept the binding pipeline or bind objects of different types together. If you’re coming from WPF, this feels natural anyway, but the solution here does not require you to implement a value converter - a simple Func<TSource, TTarget> is sufficient.

    Here’s a simple sample that performs a conversion of a boolean flag to into a corresponding Visibility enum value:

     

    [Test]
    public void Boolean_Should_Be_Converted_To_Visibility()
    {
      //create a hidden window
      Window window = new Window { Visibility = Visibiliy.Collapsed };
    
      //create a view model
      MyViewModel viewModel = new MyViewModel { IsVisible = false };
    
      //create binding that casts the Visibility into a boolean
      LambdaBinding.BindOneWay(
          () => viewModel.IsVisible,
          () => window.Visibility,
          b => b == true ? Visibility.Visible : Visibility.Collapsed;
    
      //a change in the ViewModel shows/hides the window
      viewModel.IsVisible = true;
    
      Assert.AreEqual(Visibility.Visible, window.Visibility);
    }

     

    Two-Way-Binding

    Two way binding works too, of course:

    [Test]
    public void Updates_Should_Work_Both_Ways()
    {
      //create two-way binding
      var binding = LambdaBinding.BindTwoWay(
        () => FirstStudent.Name,
        () => SecondStudent.Name);
    
      //change property on source
      FirstStudent.Name = "Peter";
      Assert.AreEqual("Peter", SecondStudent.Name);
    
      //change property on target
      SecondStudent.Name = "Parker";
      Assert.AreEqual("Parker", FirstStudent.Name);
    }

    In case you need to perform type conversion, you need to supply two converter functions for forward / reverse conversion:

    //bind a boolean property to a control's Visibility property
    var binding = LambdaBinding.BindTwoWay(
        () => ModelItem.IsEnabled,
        () => MyControl.IsVisible,
        b => b == true ? Visibility.Visible : Visibiliy.Collapsed
        v => v == Visibility.Visible ? true : false);

     

    Default Values

    In case the object graph is being broken (e.g. because the School was set to null), the target node will be automatically set to its default value (null for an object, 0 for an int etc.). However, you can also specify a default value of your own:

    //a local field to be updated
    private string schoolCity;
    
    [Test]
    public void Breaking_The_Chain_Should_Assign_Default_Value_To_Target_If_Specified()
    {
      var binding = LambdaBinding.BindOneWay(
          () => Student.School.Address.City,
          () => schoolCity,
          "[No City]");
    
      //break the source chain
      Student.School = null;
    
      //the default value was assigned to the target
      Assert.AreEqual("[No City]", schoolCity);
    }

    (btw: the above snippet also shows you that you can easily bind to a field rather than a property).

     

    Weak References

    The underlying Lambda Dependencies only use weak references so you’re not at risk of creating memory leaks. However, LambdaBinding implements IDisposable, so the proper way to clean things up would be to dispose your binding.

    Things to Consider

    Remember that that the underlying Lambda Dependencies rely on the INotifyPropertyChanged interface, so don’t expect source binding to fields (or properties that do not fire a PropertyChanged event) to magically update your targets.

     

    Download: lambda-dependencies.zip

     

    kick it on DotNetKicks.com

    Detecting Double Click Events on the WPF DataGrid

    March 21st, 2009

    Either I missed the obvious solution, or there is indeed no simple way to catch double click events on a given row of Microsoft’s WPF DataGrid.

    This snippet here fires the event whenever the grid is clicked - it doesn’t matter whether the user double-clicks into an empty area (no rows) or a row:

    <!-- fires even if the user does not click a given row -->
    <dg:DataGrid
      dg:DataGridRow.MouseDoubleClick="OnDoubleClick" />

     

    As a result, I reverted to a workaround by searching the Visual Tree of the event source for an instance of type DataGridRow. In order to find the ancestor item, I used a snippet I posted here a while ago. Here’s the full code:

     

    XAML:

    <!-- just register a listener on the grid -->
    <dg:DataGrid
      MouseDoubleClick="OnDoubleClick" />

     

    Code-Behind:

    /// <summary>
    /// Handles double-clicks on datagrid rows.
    /// </summary>
    private void OnDoubleClick(object sender, MouseButtonEventArgs e)
    {
      //search the object hierarchy for a datagrid row
      DependencyObject source = (DependencyObject) e.OriginalSource;
      var row = UIHelpers.TryFindParent<DataGridRow>(source);
    
      //the user did not click on a row
      if (row == null) return;
    
      //[insert great code here...]
    
      e.Handled = true;
    }

     

    UIHelper class providing the TryFindParent method:

    (Snippet updated: 2009.09.14)

    /// <summary>
    /// Finds a parent of a given item on the visual tree.
    /// </summary>
    /// <typeparam name="T">The type of the queried item.</typeparam>
    /// <param name="child">A direct or indirect child of the
    /// queried item.</param>
    /// <returns>The first parent item that matches the submitted
    /// type parameter. If not matching item can be found, a null
    /// reference is being returned.</returns>
    public static T TryFindParent<T>(this DependencyObject child)                               where T : DependencyObject
    {
      //get parent item
      DependencyObject parentObject = GetParentObject(child);
    
      //we've reached the end of the tree
      if (parentObject == null) return null;
    
      //check if the parent matches the type we're looking for
      T parent = parentObject as T;
      if (parent != null)
      {
        return parent;
      }
      else
      {
        //use recursion to proceed with next level
        return TryFindParent<T>(parentObject);
      }
    }
    
    /// <summary>
    /// This method is an alternative to WPF's
    /// <see cref="VisualTreeHelper.GetParent"/> method, which also
    /// supports content elements. Keep in mind that for content element,
    /// this method falls back to the logical tree of the element!
    /// </summary>
    /// <param name="child">The item to be processed.</param>
    /// <returns>The submitted item's parent, if available. Otherwise
    /// null.</returns>
    public static DependencyObject GetParentObject(this DependencyObject child)
    {
      if (child == null) return null;
    
      //handle content elements separately
      ContentElement contentElement = child as ContentElement;
      if (contentElement != null)
      {
        DependencyObject parent = ContentOperations.GetParent(contentElement);
        if (parent != null) return parent;
    
        FrameworkContentElement fce = contentElement as FrameworkContentElement;
        return fce != null ? fce.Parent : null;
      }
    
      //also try searching for parent in framework elements (such as DockPanel, etc)
      FrameworkElement frameworkElement = child as FrameworkElement;
      if (frameworkElement != null)
      {
        DependencyObject parent = frameworkElement.Parent;
        if (parent != null) return parent;
      }
    
      //if it's not a ContentElement/FrameworkElement, rely on VisualTreeHelper
      return VisualTreeHelper.GetParent(child);
    }

     

    Enjoy :-)

    Tags:

    First Anniversary

    January 16th, 2009

    Wow, already a year since my first blog post! It’s been fun and I’m far from running out of ideas - stay tuned :)

    Tags:

    Combining WPF Validation Rules and IDataErrorInfo to Resolve Conversion Errors

    January 8th, 2009

    This article discusses a few approaches to overcome binding conversion errors in WPF by combining model validation (through IDataErrorInfo) and WPF validation rules. Practically, I’m going to outline three approaches to the same solution:

    • Inline declaration
    • Using attached properties
    • Using custom binding classes

     

    image

    The Problem

    WPF validation through IDataErrorInfo is a great feature if you already have validation logic in you model. However: There is a problem if the user enters a value that cannot be written to model due to value conversion errors. Let’s start with a simple sample:

    • A TextBox is bound to a numeric Age property of your model.
    • As soon as the user enters a value in the Textbox, the property on the model is updated. The model then validates whether the entered value is valid (range from 1 to 130 years).
    • However: If the user enters a string rather than a number (e.g. “30a”), the value conversion to an integer fails. In this case, WPF does not show an error at all:

    image

     

    Karl Shifflet recently updated his article on this very subject, where he outlines an MVVM-based approach to the problem (highly recommended reading material!).

    In my case, however, I was looking for a simpler solution. I had validation and views already in place and just wanted a visual representation of invalid input that cannot be bound to the model.

     

    WPF Validation Rules to the Rescue

    And this is where the good old WPF Validation Rules come back into play:

    1. A binding with ValidatesOnDataErrors=True ensures that the model validation logic is being invoked.
    2. Additional WPF Validation Rules take care of invalid input that can not be bound to the model.

     

    <TextBox x:Name="txtAge">
    
      <TextBox.Text>
        <Binding Path="Age" ValidatesOnDataErrors="True">
          <Binding.ValidationRules>
            <rules:NumericRule />
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    
    </TextBox>

     

    That’s it already! An invalid numeric value (below minimum, above maximum) is handled by the model, everything else is caught be the NumericRule (see attached sample for the sources).

    image

     

    Simplify Markup 1: Attached Properties

    The above sample has one catch - it forces me to write rather verbose XAML. This is where attached properties come to the rescue. Here’s the same thing using an attached property:

     

    <TextBox x:Name="txtAge"
      Text="{Binding Path=Age, ValidatesOnDataErrors=True}"
      rules:Editors.TextRule="{StaticResource numericRule}"
    />

     

    In the sample above, I declared an attached property of type ValidationRule that points to by custom rule. However, depending on your case, you can make your attached property as simple/complex as you need. A great article on this subject was published by WPF master Josh Smith on CodeProject, where he outlines this exact pattern.

     

    Simplify Markup 2: Custom Binding Classes

    As an alternative to attached properties - especially in case you want to define multiple parameters - a custom binding expression might be a simpler approach. If you use a simple Decorator helper class, creating your custom binding class is a breeze:

     

    <TextBox x:Name="txtCustomBinding"
      Text="{local:RuleBinding Path=Age, MinValueOverride=20}"
    />

     

    Here’s my custom binding class, derived from BindingDecoratorBase:

    using System;
    using System.Windows.Controls;
    using System.Windows.Data;
    using Hardcodet.Wpf.ValidationRules;
    
    namespace Hardcodet.Wpf.CustomBinding
    {
      /// <summary>
      /// A binding extension that checks for a given
      /// numeric value.
      /// </summary>
      public class RuleBinding : BindingDecoratorBase
      {
        /// <summary>
        /// An optional override for the minimum value,
        /// that can be used to narrow the allowed range.
        /// </summary>
        public int? MinValueOverride { get; set; }
    
        /// <summary>
        /// Creates a new instance of the binding with default values.
        /// </summary>
        public RuleBinding()
        {
          //set default binding directives
          ValidatesOnDataErrors = true;
          UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        }
    
        /// <summary>
        /// This method is being invoked during initialization.
        /// </summary>
        /// <param name="provider">Provides access to the bound items.</param>
        /// <returns>The binding expression that is created by
        /// the base class.</returns>
        public override object ProvideValue(IServiceProvider provider)
        {
          //create the validation rule
          ValidationRule rule;
          if (MinValueOverride.HasValue)
          {
            //create a rule that also narrows the minimum value
            rule = new MinNumericRule() {MinValue = MinValueOverride.Value};
          }
          else
          {
            //just make sure the value is numeric
            rule = new NumericRule();
          }
    
          Binding.ValidationRules.Add(rule);
    
          //delegate binding creation etc. to the base class
          object val = base.ProvideValue(provider);
          return val;
        }
      }
    }

     

    The attached sample shows you all the techniques I described above.

    Download sample project: validationrules.zip

    kick it on DotNetKicks.com

    Tags: ,