Introduction to attached behaviors

August 30, 2008

I just published an article on CodeProject that introduces the popular technique of attached behaviors in WPF.  The demo app is an extension of the demo provided by my ‘Simplifying the WPF TreeView by Using the ViewModel Pattern‘ article.  The new article shows how you can attach a behavior to TreeViewItem so that it scrolls into view upon being selected by a ViewModel object.  If you’re interested, here’s the link:

http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx

Enjoy!

Advertisement

Filtering a list of items with the PropertyFilterGroupView control

August 26, 2008

I have been working on a new component that allows you to filter any list of items shown in a WPF user interface.  My new PropertyFilterGroupView is definitely still a work-in-progress, so please do not drop this control into a production WPF application just yet!  If you are interested in this, please leave me a comment with constructive criticism, feature requests, bug reports, etc.  I’m interested to see what people have to say about it.  The source code is available at the end of this blog post.

Binding to a collection of objects really means binding to an ICollectionView implementation that wraps the underlying collection.  One property exposed by ICollectionView is Filter, of type Predicate<object>.  When a filter is applied, all controls bound to the view will display only the items that passed through the filter, or were “filtered in.”  PropertyFilterGroupView is a very fancy and elaborate way to assign the Filter property of an ICollectionView.

Below is a screenshot of the demo application when it first loads up.  The control in the Expander up top is the PropertyFilterGroupView control.  The ListBox and ListView seen beneath it are bound to the ICollectionView that the PropertyFilterGroupView affects.  When the app first loads up all items in both lists are visible, as seen below:

After applying a few filters, the two lists display a subset of the original set of items.  The items still seen in the lists are the ones that satisfy all of the filters applied.  The modified UI looks like this:

In this demo app, the list of items shown in the UI is a collection of Person objects.  The Person class exposes some properties, as seen below:

Now that you know what shape the data objects have, let’s see how to configure the PropertyFilterGroupView control so that it allows the user to filter a list of Person objects.  The following XAML is from the Window1.xaml file in the demo project:

Each property on the Person object that the user should be able to filter on has a PropertyFilter object added to the filter group.  PropertyFilter is a class I made which represents a filter that determines whether a certain property on an object satisfies a criterion.  The user can select the filter’s criterion via a ComboBox in the PropertyFilterViewGroup control.

When you create a PropertyFilter, you must set the PropertyName and PropertyType properties to valid values.  If you do not set them, or set them to invalid values, an exception will be thrown when that filter is used.  The PropertyName property allows you to indicate which property to filter on, and PropertyType must be set to the data type of that property.  If you want the property’s name to be more user-friendly, set the DisplayName property to a more readable name.

Look at the last PropertyFilter object again, which filters on the MaritalStatusID property.  That filter has two additional properties set on it: PropertyConverter and DisplayType.  The former is set to the IValueConverter used by the ListView to translate an integer to a value from the MaritalStatus enum.  The ListView uses that converter in this column:

The PropertyFilter that filters the MaritalStatusID property needs access to that value converter so that it, too, can transform the integer value into the corresponding enum value.  Without that in place, the user would not be able to filter on the text in the Marital Status column, but only the underlying numeric identifiers.

The DisplayType property is set on that PropertyFilter so that it can intelligently decide what the available filtering criteria are for that property, such as ‘Starts With’ and ‘Is Less Than’.  The list of filtering criteria for, say, a numeric type is not the same as for text, which is not the same for Booleans.  To ensure that the filtering criteria makes sense for a property whose value is passed through a value converter, you must indicate what type the output value should be treated as for filtering purposes.  I chose String as the DisplayType for the MaritalStatusID filter, because enum values are easy to compare via their textual representations.

The PropertyFilterGroupView control also has its CollectionView property set.  It is bound to the inherited DataContext. To ensure that this property is able to pick up a reference to a CollectionView, I created a CollectionViewSource as the Window’s DataContext.  That XAML is below:

As I mentioned before, this project is a work-in-progress.  There are some big pieces of the puzzle missing.  For example, I do not yet support filtering on properties of type DateTime.  However, with that said, I encourage you to try this component out and see what you think.  I’m open for suggestions…

Download the source code here: PropertyFiltering Source Code .  Be sure to change the file extension from .DOC to .ZIP and then decompress the file.


Removing the value applied by an animation

August 21, 2008

By default, the final value of an animation will indefinitely apply to the property it is animating.  This is because the default value of an animation’s FillBehavior property is ‘HoldEnd.’  Since only a dependency property (DP) can be animated in WPF, and the DP value resolution algorithm treats an animation’s value as a higher priority source than a local value, if you try to set an animated property to a certain value in code, your value will be ignored.

For example, suppose I want to animate the Height property of a Rectangle element to 200.  I could create the following XAML to accomplish that task:

When that Rectangle is loaded into the UI, it would grow in height from 10 to 200 logical pixels over the course of two seconds.  Since the DoubleAnimation applied to the Height property is using the default FillBehavior, which continues to apply the value 200 to Height after the animation finishes running, setting the element’s Height in code would have no effect.  What I would need to do is remove that animation from the property, so that the value resolution mechanism built into the DP system would use my locally set value.

The trick to removing an animation’s value from a DP is to begin a “null animation” against that property.  This is quite simple to do, as it only requires one method call:

After running those two lines of code, the Rectangle would immediately become 100 logical pixels tall.  UIElement and ContentElement both define the BeginAnimation method, so all elements in WPF have this ability built in.


Podder Skinning Competition Hall of Fame

August 12, 2008

There were five contestants in the Podder Skinning Competition.  Each of them submitted something very cool and interesting, but the three judges had to pick one winner out of them.  After much deliberation and conversation, we decided that the winning skin is BOConnor by Brendan O’Connor.  Congratulations, Brendan!

BOConnor

BOConnor

Here is a brief bio about Brendan:

Brendan is 25 years old and currently the lead software developer for a Healthcare company in Ireland called Technical Ideas.  He studied Computing and Software development at college for 4 years and has been with the company since it began in 2004.  The main product they develop is called Socrates. It is a software product used by GP’s, Nurses and many other Healthcare professionals which manages an Electronic Health Record for patients within their practice and also the day to day running of the practice.  Currently they develop in C# .NET WinForms with SQL Server 2005.  Brendan had never used WPF until he decided to enter the Podder Skinning competition.  He has been following it for many months, briefly reading articles from the WPF posse posted at CodeProject.  He also had some books on WPF lying around for some months untouched and once the competition was extended, saying he would enter just to give him an excuse to try out WPF and see what it was like.

The competition had three judges, including myself.  The other two were Marlon Grech and Jeremiah Morrill.  I appreciate their help and thoughtful feedback.

Here are all of the contestants and links to their submitted Podder skins:

Gary Winter : http://gwinter8217.googlepages.com/home

Rudi Grobler : http://dotnet.org.za/rudi/archive/2008/07/31/my-podder-skins.aspx

Jobi : http://jobijoy.blogspot.com/2008/08/podder-skinning-another-wpf-contest.html

Brendan : http://www.bstash.com/Podder/Podder.zip

Boris : http://cid-f2590eadde4ae4bc.skydrive.live.com/browse.aspx/Public

I’d like to thank everyone who took the time to submit a skin, and those who helped judge the skins!


The Podder Skinning Competition is a success!

August 4, 2008

It seems that extending the Podder Skinning Competition deadline by a month worked out well.  Today was the deadline, and there are five contestants!  Technically one of them was a few hours past the deadline, but I can tell he really put his all into this, so I’m going to let it slide.  😉

Now the judges will decide which of the contestants is the winner.  Since there were five entries, there will be only one winner, according to the rules laid out in the competition’s write-up.  I hope to have the final decision made within a few days or a week.  Stay tuned to see who won…

All of the submissions can be found in the comments of this post:

https://joshsmithonwpf.wordpress.com/podder-skinning-competition/#comments


Article about CheckBoxes in a WPF TreeView

August 1, 2008

After much experimentation, prodding, and poking (and some help from Dr. WPF) I’ve found a great way to put CheckBox controls into TreeViewItems.  There are some subtle and irritating issues that I needed to figure out and work around, particularly related to keyboard navigation.  However, the deed is done and now you can read all about it here:

http://www.codeproject.com/KB/WPF/TreeViewWithCheckBoxes.aspx

At the end of the article, I point out a bug in the CheckBox control that is specific to the Aero theme.  :-\