Sunday 25 August 2013

Norwegian Developers Conference review part2

The second part of the ndc reviews, which I should definitely hurry with because of the approaching NDC London, which will surely bring another batch of brilliant presentations...

Dan North: Patterns of Effective Teams
Main topics of this lecture were pair programming, teaming up people of different skill level, scrum stand-ups, code reviews/critique and hack days. The general agile food for though you can expect from Dan North focused on building a team and working in a team. I really like all of his ideas and hints, though some of them feel a tad bit too idealistic.

Robert C. Martin: Principles of Component Design.
Another show by Uncle Bob, going through historical beginnings of modular design and dividing code into separate libraries. Through dependency and coupling, up to inversion of control and programming against abstractions.


Michael Heydt: Concurrent and High-Performance Programming in .NET with TPL, async/await, and Dataflow
I had high hopes for this presentation due to the trading app that was used as a showcase of different parallel code execution techniques - which would go along with mine line of work. Unfortunately I think that the presenter wanted to touch too many subjects at once, briefly going through a little bit of everything not having enough time for a more thorough description. It also seemed that he had problems with conveying some of the thoughs, which made some sentences unclear at first. Another thing is that NDC did not post the whole recording which is a real shame, because despite of some minor slip ups it was an interesting lecture.

Thursday 1 August 2013

Adding Drag and drop behaviour to ItemsControls Part 1

        Because drag and drop in WPF can be quite tricky I though I'm gonna share my implementation (based on other implementations I found online) of it. What I had in mind when I wrote it, was ease of use, especially the xaml side of things.

        This implementation should work with all ItemsControl derived controls (like ListBox or DataGrid). It's a static behaviour that can be hooked up to any ItemsControl in XAML. It is also based on groups. You can only drag and drop between controls added to specific groups. The behaviour internally hold 2 collections with drag sources and drop targets with against specific groups. Additionally there's always a default group created in case the group was not specified in XAML.

Code Snippet
  1. public static class DragAndDropBehaviour
  2. {        
  3. private static Dictionary<String, List<ItemsControl>> dragSources;
  4. private static Dictionary<String, List<ItemsControl>> dropTargets;
  5. // Mouse click coordinates
  6. private static System.Windows.Point startPoint;
  7.  
  8. public static readonly DependencyProperty IsDropTargetProperty =
  9.    DependencyProperty.RegisterAttached("IsDropTarget", typeof(bool),
  10.    typeof(DragAndDropBehaviour),
  11.    new UIPropertyMetadata(false, IsDropTargetUpdated));
  12.  
  13. public static readonly DependencyProperty IsDragSourceProperty =
  14.     DependencyProperty.RegisterAttached("IsDragSource", typeof(bool),
  15.     typeof(DragAndDropBehaviour),
  16.     new UIPropertyMetadata(false, IsDragSourceUpdated));
  17.  
  18. public static readonly DependencyProperty GroupNameProperty =
  19.     DependencyProperty.RegisterAttached("GroupName", typeof(String),
  20.     typeof(DragAndDropBehaviour),
  21.     new UIPropertyMetadata("", GroupNameUpdated));

      Above we've got the 2 collections I mentioned. Each dictionary sets a group name against a list of ItemsControls in that group. Group names from both dictionaries must match to make drag and dropping possible.

      There are 3 attached properties (I'm not their setters and getters on purpose to make it brief). We set IsDropTarget to true on a control if we want to allow it to receive the drop action. Same with IsDragSource for drag sources. Group name should be set to any string we want, which describes the group which participates in the drag and dropping behaviour.

Code Snippet
  1. private static void IsDragSourceUpdated(DependencyObject dp,
  2.     DependencyPropertyChangedEventArgs args)
  3. {          
  4.     InitializeDragLists();
  5.  
  6.     ItemsControl DragSource = dp as ItemsControl;
  7.     
  8.     if ((bool)args.NewValue == true)
  9.     {
  10.         if (dragSources.Any(p => p.Key == GetGroupName(dp)))
  11.         {
  12.             dragSources[GetGroupName(dp)].Add(DragSource);
  13.         }
  14.     }
  15.  
  16.     DragSource.PreviewMouseMove -= new MouseEventHandler(OnMouseMove);
  17.     DragSource.PreviewMouseMove += new MouseEventHandler(OnMouseMove);
  18.  
  19.     DragSource.PreviewMouseLeftButtonDown -=
  20.         new MouseButtonEventHandler(OnLeftButtonDown);
  21.     DragSource.PreviewMouseLeftButtonDown +=
  22.         new MouseButtonEventHandler(OnLeftButtonDown);
  23.  
  24.     DragSource.Unloaded += new RoutedEventHandler(DragSource_Unloaded);
  25.     DragSource.Loaded += new RoutedEventHandler(DragSource_Loaded);
  26. }

        First of the two change callbacka called has to initialize those two collections. We also need to add the control which we have adorned with IsDragSource property to the dragSources collection. Additionally 4 events have to be handled in the drag and drop process:
- PreviewMouseLeftButtonDown - to aquire position starting position of the drag process
- OnMouseMove - we start dragging on move, only, if left mouse button has been clicked and is being pressed. And only, if some minimum distance has been reached.
- Unloaded/Loaded - when the visual tree is loaded or unloaded during our work with the UI, we need to make sure that collections are being emtpied or populated again We don't multiple instances of the same control added to those lists.

In the next part I'll describe the rest of methods used.