Master WPF on your iPhone

February 16, 2012

After being obsessed with WPF for so many years, I can’t just forget about it. Even though my focus is now on iOS development, I still think that WPF is an awesome platform. That’s why I wrote an iPhone app named Master WPF. It contains 500 questions, spread across 28 topics, that I painstakingly wrote, organized, and proofread until my eyes bled. The questions will help any WPF developer sharpen their skills.

It’s for WPF noobs, gurus, and everyone in between.

Master WPF on your iPhone or iPod Touch

Master WPF on your iPhone or iPod Touch

You can download Master WPF for free on your iPhone or iPod Touch, running iOS 5 or greater. The app comes with 15 free questions so that you can try it out. If you decide that you want to master WPF with my app, you can make a small in-app purchase to unlock all 500 questions.

Think of it as a donation to a recovering WPF addict.

Screenshots of Master WPF

Screenshots of Master WPF

For more info about Master WPF, please check out http://masterwpf.com

Advertisement

Article about Service Locator, MVVM, and MessageBoxes

April 1, 2010

I just published an article titled ‘Using a Service Locator to Work with MessageBoxes in an MVVM Application‘ on CodeProject.  It’s one solution to the now canonical question of how to work with message boxes in an MVVM app, either WPF or Silverlight.  The article gives an introduction to the Service Locator pattern, in case you are not yet familiar with that concept, and then dives into an example of how to leverage it.  The end result is a simple, testable, extensible way to work with message boxes from ViewModel objects.

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

By the way, I found out today that I got the Microsoft MVP award again.  Four years in a row!  Woohoo!! 😀


Introducing ContentControl3D

February 23, 2009

A couple years ago, Ian Griffiths blogged about a way to create flippable list items in WPF.  His approach involves using a VisualBrush to display the 2D content in 3D space, because he implemented it before Viewport2DVisual3D was introduced in .NET 3.5.  Also, his approach was not very easy to reuse in many applications because the functionality was not placed into a custom control.  Tonight, I decided to remedy this by making use of Viewport2DVisual3D in a reusable control.

The code associated with this post is a working prototype.  I intend on turning this into something more complete, but want to share it with the world as soon as possible, hoping to get some feedback and feature requests early on.

I created a control that derives ContentControl, called ContentControl3D.  It allows you to assign the BackContent property to specify what should be shown after you first flip the control over.  The Content property, inherited from ContentControl, specifies what to display on the front side of the surface.  You can also assign the BackContentTemplate property a DataTemplate, if BackContent is set to a data object (instead of a visual element).

Here is a screenshot of the demo application when it first loads up:

front
After clicking the “Flip Over” button, the UI performs an animated rotation, leaving you with a view of the back side of the surface.  This is shown below…

back
Naturally, you can put whatever content you want on the front and back sides.

Here is the XAML which configures the ContentControl3D in the demo window:

xaml
If you would like to check this control out, you can download the source code here: ContentControl3D Source Code.  NOTE: Be sure to change the file extension from .DOC to .ZIP and then decompress the file.

Your feedback is welcome.  Thanks!


The Initially Selected Item when Binding to a Grouped ICollectionView

September 18, 2008

I found a bug in WPF today.  That doesn’t happen very often, but today was one of those days.  If you bind a ListBox to an ICollectionView that has one or more PropertyGroupDescriptions in its GroupDescriptions collection, the initially selected item’s IsSelected property is set to true.  This might not sound like a bug, but it turned out to be one of those issues that took an hour of my life away.  This blog post shows the workaround I came up with.

Suppose you have a collection of PersonViewModel instances, where the class is defined as:

Also suppose that you have these resources set up, and they are applied to the ListBox that displays the list of PersonViewModel objects:

The ListBox is declared as:

The UI also has another ListBox that is not bound to a grouped collection view, and also, beneath the ListBoxs, a TextBlock that shows the selected PersonViewModel’s Bio property. When you run the app, it looks like this:

If you select Steve Smith from the left ListBox, the UI updates accordingly:

However, if you then select Dave Brown again from the right ListBox (the one bound to grouped data), watch what happens:

Yikes!!  The left ListBox and Bio area did not update.  Why not?  Because it turns out that the initially selected item in a ListBox bound to a grouped ICollectionView has its IsSelected property set to true, as a local value.  According to rules of WPF, a local value takes precedence over the value provided by a binding.  So, the binding established on the ListBoxItem’s IsSelected property is overwritten by a local value.

Until Microsoft fixes the bug I reported about this we are stuck using a workaround.  Here’s what I came up with, as seen in the window’s code-behind file.

You can download the demo project here.  This application was compiled in Visual Studio 2008 against .NET 3.5 SP1.  You must change the file extension from .DOC to .ZIP and then decompress it.


Conserving screen real estate via the adorner layer

September 14, 2008

I spent the weekend building and expanding on my previous work adorning XamDataGrid with editor controls.  I made leaps and bounds of progress, and am very excited about the result.  As much of the functionality that can be abstracted away now lives as an attached behavior, called DisplayAdornerEditors.  I wrote a big post about it on my other blog, so if you’re interested, I highly recommend you check it out here!

WPF is amazing!


Using Attached Behaviors to Add Currency Support to XamDataGrid

September 9, 2008

I just found another great use for attached behaviors!  I used them to add to XamDataGrid the equivalent behavior of what WPF list controls get for free via the IsSynchronizedWithCurrentItem property.  You can check out how it works here.


Synchronizing the width of elements in an ItemsControl

September 6, 2008

When I use an ItemsControl (or subclass of ItemsControl, such as ListBox) to display a list of items, I often want the width of an element in each item to match the width of the equivalent elements displayed for all other items.  That is easy to achieve by setting the Width property of an element in the DataTemplate used by the ItemTemplate property, but using hard-coded width and height values is generally considered to be a bad practice.  It’s better to not specify a width, and let the element figure out how big it should be based on its content.  But, if the element created for each item in the ItemsControl is sizing to its own content, that means that the sizes of all elements created for items will usually not be equal to each other.

For example, the screenshot below displays an ItemsControl populated with some strings.  The ItemsControl has an ItemTemplate that contains a TextBlock with a light blue background color.  Notice how each item is just wide enough to display its content:

What I would like, however, is to have each item be equally wide, and that the width of all items is the width required by the widest item.   In other words, all of the TextBlocks should be as wide as the TextBlock that contains the word ‘Whatever’.  As I mentioned before, I could solve this problem by hard-coding a Width for the TextBlocks, but that is a very fragile solution.

It turns out that there is a very clean and simple solution to this problem.  The trick is to rely on a not-so-often used feature of the Grid panel.  Grid has an attached property called IsSharedSizeScope, which I will set to true on the ItemsControl.  I then wrap the TextBlock in the ItemControl’s ItemTemplate inside a Grid, and give that Grid a single ColumnDefinition whose SharedSizeGroup property is set to some arbitrary identifier.  Here is that XAML:

When I run the application now, the UI looks like this:

You can download the demo project here.  Be sure to change the file extension from .DOC to .ZIP and then decompress the file.


Using MVVM to work with CheckBoxes in XamDataGrid

September 4, 2008

On my other blog, I published a way to put CheckBoxes into the XamDataGrid.  The interesting aspect of the implementation, in my opinion, is how it uses the Model-View-ViewModel pattern to maintain the check state of each CheckBox.  Since I put a CheckBox into the header area above the CheckBoxes in each row, I used a ViewModel object to encapsulate the logic that figures out what state the header CheckBox should have, and how to update the state of each row’s CheckBox.  It’s just another example of how great MVVM is when working with WPF.

Here’s a screenshot of that demo app:

You can read that blog post here.


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!


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.