WPF application patterns and Unit Testing
Josh Smith, prolific Code Project writer and blogger, has written a great article about MVC (or M-V-poo, as the doctor would say!) and unit testing of WPF apps. The article can be found on Code Project:
Josh Smith, prolific Code Project writer and blogger, has written a great article about MVC (or M-V-poo, as the doctor would say!) and unit testing of WPF apps. The article can be found on Code Project:
This is a simple snippet which helps you to find a specified parent of a given WPF dependency object somewhere in its visual tree:
(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); }
This snippet works with arbitrary dependency objects that are of Type Visual or Visual3D. So let’s say you need a reference to the Window that hosts a given Button control somewhere, all you need is this:
Button myButton = ... Window parentWindow = UIHelper.TryFindParent<Window>(myButton);
The above TryFindParent method also makes it easy to get an item at a given position. The method below performs a hit test based on a given position. If hit testing does not return the requested item (e.g. a clicked CheckBox on a tree, while you are keen on the TreeViewItem that hosts the CheckBox), the procedure delegates the lookup to TryFindParent.
This comes in very handy for mouse-related events if you just need to now what’s under your mouse pointer:
/// <summary> /// Tries to locate a given item within the visual tree, /// starting with the dependency object at a given position. /// </summary> /// <typeparam name="T">The type of the element to be found /// on the visual tree of the element at the given location.</typeparam> /// <param name="reference">The main element which is used to perform /// hit testing.</param> /// <param name="point">The position to be evaluated on the origin.</param> public static T TryFindFromPoint<T>(UIElement reference, Point point) where T:DependencyObject { DependencyObject element = reference.InputHitTest(point) as DependencyObject; if (element == null) return null; else if (element is T) return (T)element; else return TryFindParent<T>(element); }
I abandoned the LGPL in favor of the Code Project Open License (CPOL) this morning (starting with the TreeView control), and I was pretty surprised that Googling for the license didn’t show up the license’s home page in the upper ranks.
As a result, I decided to write my first Wikipedia article in order to make this – IMO very nice license – at bit more accessible. The article itself is no big deal, but I must say, writing on Wikipedia is very convenient – I think I might do that again 🙂
I included a newsletter module into the blog – in case you would like to stay up-to-date about what’s going on here, you can now subscribe to a specific newsletter.
I’ll provide newsletter categories for all projects that are being released here, starting with the WPF TreeView, so this will be a convenient way to get notified if a new version has been made available.
Robby Ingebretsen published the source code of his incredibly useful (and beautiful!) Kaxaml on CodePlex. I often prefer Kaxaml over Visual Studio because it combines a bunch of really smart features with a very nice UI that just makes it a pleasure to work with. I’m definitely looking forward to have a peek at its internals 🙂
CodePlex project site: http://www.codeplex.com/Kaxaml
Official Kaxaml download site: http://www.kaxaml.com
A tutorial is now available on Code Project, so check the article for a detailed overview. And please leave your rating if you like the control 🙂
http://www.codeproject.com/KB/WPF/versatile_treeview.aspx
Update: The latest version is currently only available through the download link below. I’ll update the CodeProject article once the current filtering mechanism has been rewritten:
Download: wpf-treeview.zip (Current version: 1.0.7, updated 2008.04.06)
This is a little something I’ve been working on for a while: A replacement (or better: enhancement) of WPF’s built-in TreeView control.
I became aware of the default control’s limitations during my last project – I naturally started with hierarchical data templates, but was soon confronted with quite a few issues: I missed a simple API to control the tree, and styling of the tree’s nodes proved hard as well. Furthermore, WPF’s TreeView tends to fire all sorts of SelectedItemChanged events if it’s being refreshed or rebound, which caused side-effects with TwoWay data binding.
However, instead of posting a rant that probably nobody would ever read (let alone care about), I worked on an alternative. Here’s the tree’s main features at a glance:
<local:ProductTree x:Name="MyTree" Items="{Binding Source={StaticResource Shop}, Path=Products}" SelectedItem="{Binding ElementName=MyProductList, Path=ActiveItem, Mode=TwoWay}" NodeContextMenu="{StaticResource CategoryMenu}" TreeNodeStyle="{StaticResource SimpleFolders}" TreeStyle="{StaticResource SimpleTreeStyle}" SelectedItemChanged="OnSelectedItemChanged" />
//bind flat list of business objects to tree List<Product> products = GetProducts(); myTree.Items = products; //select a given item Product foo = GetBestSellingProduct(); myTree.SelectedItem = foo; //SelectedItem is of type Product - no casts required Product bar = myTree.SelectedItem;
All this goodness comes at a price: The TreeViewBase class that provides this functionality, is abstract. This means you have to write a little code yourself. However, you’ll probably manage with 3 lines of code, as the base control just needs to know 3 things:
Here’s the complete implementation of the sample application’s tree control:
//a tree control that handles only ShopCategory objects public class CategoryTree : TreeViewBase<ShopCategory> { //the sample uses the category's name as the identifier public override string GetItemKey(ShopCategory item) { return item.CategoryName; } //returns subcategories that should be available through the tree public override ICollection<ShopCategory> GetChildItems(ShopCategory parent) { return parent.SubCategories; } //get the parent category, or null if it's a root category public override ShopCategory GetParentItem(ShopCategory item) { return item.ParentCategory; }
I’m planning to write a CodeProject article for this one, but for now, it’s only available through my place without a tutorial. However: The library comes with a sample project that shows pretty much all features of the control. Project format is currently VS2008 only, but binaries which target .NET 3.0 are included. Enjoy!