Archive for February, 2013

ObservableCollection – Extension Methods

When you ever used the CollectionView of the ObservableCollection and wanted to get or set the CurrentItem you might have noticed that it requires much more typing than expected.

For that purpose I created the following extension methods for the ObservableCollection.

 

  public static class CollectionExtensions
  {
    /// <summary>
    /// This method returns the current item of the given collection.
    /// </summary>
    /// <typeparam name="T">The type of the elements in the collection.</typeparam>
    /// <param name="source">The collection.</param>
    public static T GetCurrentItem<T>(this IEnumerable<T> source)
    {
      if (source == null)
        return default(T);
      var collectionView = CollectionViewSource.GetDefaultView(source);
      return (T)collectionView.CurrentItem;
    }

    /// <summary>
    /// This method returns the current position within the given collection.
    /// </summary>
    /// <typeparam name="T">The type of the elements in the collection.</typeparam>
    /// <param name="source">The collection.</param>
    public static int GetCurrentPosition<T>(this IEnumerable<T> source)
    {
      if (source == null)
        return -1;
      var collectionView = CollectionViewSource.GetDefaultView(source);
      return collectionView.CurrentPosition;
    }

    /// <summary>
    /// This method sets the current item of the given collection.
    /// </summary>
    /// <typeparam name="T">The type of the elements in the collection.</typeparam>
    /// <param name="source">The collection.</param>
    /// <param name="item">The item which should be set as the current one.</param>
    public static void SetCurrentItem<T>(this IEnumerable<T> source, T item)
    {
      if (source == null) return;
      var collectionView = CollectionViewSource.GetDefaultView(source);
      collectionView.MoveCurrentTo(item);
    }

    /// <summary>
    /// This method moves the current item to the first.
    /// </summary>
    /// <typeparam name="T">The type of the elements in the collection.</typeparam>
    /// <param name="source">The collection.</param>
    public static void MoveCurrentToFirst<T>(this IEnumerable<T> source)
    {
      if (source == null) return;
      var collectionView = CollectionViewSource.GetDefaultView(source);
      collectionView.MoveCurrentToFirst();
    }

    /// <summary>
    /// This method moves the current item to the previous.
    /// </summary>
    /// <typeparam name="T">The type of the elements in the collection.</typeparam>
    /// <param name="source">The collection.</param>
    public static void MoveCurrentToPrevious<T>(this IEnumerable<T> source)
    {
      if (source == null) return;
      var collectionView = CollectionViewSource.GetDefaultView(source);
      collectionView.MoveCurrentToPrevious();
    }

    /// <summary>
    /// This method moves the current item to the next.
    /// </summary>
    /// <typeparam name="T">The type of the elements in the collection.</typeparam>
    /// <param name="source">The collection.</param>
    public static void MoveCurrentToNext<T>(this IEnumerable<T> source)
    {
      if (source == null) return;
      var collectionView = CollectionViewSource.GetDefaultView(source);
      collectionView.MoveCurrentToNext();
    }

    /// <summary>
    /// This method moves the current item to the last.
    /// </summary>
    /// <typeparam name="T">The type of the elements in the collection.</typeparam>
    /// <param name="source">The collection.</param>
    public static void MoveCurrentToLast<T>(this IEnumerable<T> source)
    {
      if (source == null) return;
      var collectionView = CollectionViewSource.GetDefaultView(source);
      collectionView.MoveCurrentToLast();
    }

    /// <summary>
    /// This method sets the current position withing the given collection
    /// </summary>
    /// <typeparam name="T">The type of the elements in the collection</typeparam>
    /// <param name="source">The collection</param>
    /// <param name="index">The new position</param>
    public static void SetCurrentPosition<T>(this IEnumerable<T> source, int index)
    {
      if (source == null) return;
      var collectionView = CollectionViewSource.GetDefaultView(source);
      collectionView.MoveCurrentToPosition(index);
    }

    /// <summary>
    /// Removes the items from the collection according to the predicate.
    /// </summary>
    /// <param name="source">The source.</param>
    /// <param name="predicate">The predicate.</param>
    public static void Remove<T>(this ICollection<T> source, Func<T, bool> predicate)
    {
      if (source == null) return;
      var itemsToRemove = source.Where(predicate).ToList();
      foreach (var item in itemsToRemove)
        source.Remove(item);
    }
}
Advertisements

WPF – Send keys

Hi guys,

if you come from the WinForms age you might know the SendKeys class and the SendKeys.Send method, which allows you to send keys to the keyboard.
Meaning that you can simulate the pressing of a key.

But in WPF this class is no longer present. Instead of this class you can use the InputManager and feed it with the KeyEventArgs which will then be processed.
I created a small class which simplyfies this process.

public static class SendKeys
  {
    /// <summary>
    ///   Sends the specified key.
    /// </summary>
    /// <param name="key">The key.</param>
    public static void Send(Key key)
    {
      if (Keyboard.PrimaryDevice != null)
      {
        if (Keyboard.PrimaryDevice.ActiveSource != null)
        {
          var e1 = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, Key.Down) {RoutedEvent = Keyboard.KeyDownEvent};
          InputManager.Current.ProcessInput(e1);
        }
      }
    }
  }

You can simply call the SendKeys.Send method like you did it in WinForms.

Have fun!

WPF – Custom IsSynchronizedWithCurrentItem implementation

Hi guys,

if you ever missed the IsSynchronizedWithCurrentItem property in one of your controls you might need this.
Well basically you can enable a feature using this property which is synchronizing the selected item of your Control (ListBox, ComboBox, etc.) with the current item of the collection to which you bind to.

In my case I needed this feature in the Telerik RadListBox. Therefore I created an attached property which simulates this feature.
Basically what I’m doing is the following:

  • When the SelectedItem in the ListBox was changed => update the CurrentItem in the Collection
  • When the CurrentItem in the Collection was changed => update the SelectedItem of the ListBox

The tricky part here is that the user might bind a new collection to the control. Such that you have to notice that the collection was changed and register the events for the new collection.
Therefore I used this ListBoxSources-Dictionary which contains the key value pairs of the listboxes and their corresponding collections.
If the collection is different from the one it has before we know that it was changed and have to unregister the events in the old collection and register then in the new collection.

Here is the code I was talking about:

 /// <summary>
  ///   This class contains a few useful extenders for the ListBox.
  /// </summary>
  public class RadListBoxExtensions : DependencyObject
  {
    private static readonly Dictionary<RadListBox, object> ListBoxSources = new Dictionary<RadListBox, object>();

    public static readonly DependencyProperty IsSynchronizedWithCurrentItemProperty = DependencyProperty.RegisterAttached("IsSynchronizedWithCurrentItem", typeof (bool), typeof (RadListBoxExtensions), new UIPropertyMetadata(default(bool), OnIsSynchronizedWithCurrentItemChanged));

    /// <summary>
    ///   Returns the value of the IsSynchronizedWithCurrentItemProperty
    /// </summary>
    /// <param name="obj">The dependency-object whichs value should be returned</param>
    /// <returns>The value of the given property</returns>
    public static bool GetIsSynchronizedWithCurrentItem(DependencyObject obj)
    {
      return (bool) obj.GetValue(IsSynchronizedWithCurrentItemProperty);
    }

    /// <summary>
    ///   Sets the value of the IsSynchronizedWithCurrentItemProperty
    /// </summary>
    /// <param name="obj">The dependency-object whichs value should be set</param>
    /// <param name="value">The value which should be assigned to the AutoScrollToCurrentItemProperty</param>
    public static void SetIsSynchronizedWithCurrentItem(DependencyObject obj, bool value)
    {
      obj.SetValue(IsSynchronizedWithCurrentItemProperty, value);
    }

    /// <summary>
    ///   This method will be called when the IsSynchronizedWithCurrentItem property was changed
    /// </summary>
    /// <param name="s">The sender (the RadListBox)</param>
    /// <param name="e">Some additional information</param>
    public static void OnIsSynchronizedWithCurrentItemChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
    {
      var listBox = s as RadListBox;
      if (listBox != null)
      {
        var newValue = (bool) e.NewValue;
        var selectionChangedWorker = new SelectionChangedEventHandler((s1, e2) => OnSelectionChanged(listBox, listBox.SelectedItem));
        if (newValue)
        {
          listBox.Loaded += OnLoaded;
          listBox.SelectionChanged += selectionChangedWorker;
        }
        else
        {
          listBox.Loaded -= OnLoaded;
          listBox.SelectionChanged -= selectionChangedWorker;
        }
      }
    }

    /// <summary>
    ///   Called when when the listbox was loaded.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">
    ///   The <see cref="DependencyPropertyChangedEventArgs" /> instance containing the event data.
    /// </param>
    private static void OnLoaded(object sender, RoutedEventArgs e)
    {
      var listBox = sender as RadListBox;
      if (listBox == null)
        return;
      var collection = listBox.ItemsSource;
      ActivateCollectionIfNecessary(listBox, collection);
    }

    /// <summary>
    ///   Called when the selection was changed.
    /// </summary>
    /// <param name="listBox">The list box.</param>
    /// <param name="selectedItem">The selected item.</param>
    private static void OnSelectionChanged(RadListBox listBox, object selectedItem)
    {
      var collection = listBox.ItemsSource;
      ActivateCollectionIfNecessary(listBox, collection);
      var defaultView = CollectionViewSource.GetDefaultView(collection);
      if (defaultView != null)
        defaultView.MoveCurrentTo(selectedItem);
    }

    /// <summary>
    ///   Activates the collection if necessary.
    /// </summary>
    /// <param name="listBox">The listbox.</param>
    /// <param name="collection">The collection.</param>
    private static void ActivateCollectionIfNecessary(RadListBox listBox, object collection)
    {
      if (!ListBoxSources.ContainsKey(listBox))
        ListBoxSources.Add(listBox, collection);
      else if (ListBoxSources[listBox] == collection)
        return;
      var oldCollection = ListBoxSources[listBox];
      var newView = CollectionViewSource.GetDefaultView(collection);
      var currentChangedWorker = new EventHandler((s1, e2) => listBox.SelectedItem = newView.CurrentItem);

      if (oldCollection != null)
      {
        var oldView = CollectionViewSource.GetDefaultView(oldCollection);
        if (oldView != null)
          oldView.CurrentChanged -= currentChangedWorker;
      }
      ListBoxSources[listBox] = collection;

      if (newView != null)
      {
        newView.CurrentChanged += currentChangedWorker;
        listBox.SelectedItem = newView.CurrentItem;
      }
    }
}

Have fun!