Skip Navigation LinksHome > View Post

Reason 7. The ListView

Earlier I introduced a series of posts entitled 10 reasons to consider WPF for your next desktop application. If you haven't read the intro yet, better head on back and read it first.

Long term readers of this blog may recall my love of the ListView in Windows Forms. In the post that introduced my PropertyListView control I briefly mentioned why I'm a big fan of the ListView.

"I use the ListView control in my WinForm applications a lot. I mainly use it in Details mode where you get multiple columns just like you do in Windows Explorer. This is also the reason I use it so much - it's familiar and it looks good too. "

Well I've got some good news for likeminded ListView fans - things just got much better with WPF.

As with all things WPF, databinding has been baked into the ListView from the start and it works a treat. To create a simple list using the same object model as the previous examples in this series is as easy as this:

<ListView x:Name="_lstBooks" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True">
    <ListView.View>
        <GridView>
            <GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Name" />
            <GridViewColumn DisplayMemberBinding="{Binding Author}" Header="Author" />
            <GridViewColumn DisplayMemberBinding="{Binding CustomerRating}" Header="Customer Rating" />
        </GridView>
    </ListView.View>
</ListView>

Basic List View

And if we wanted to use our funky RatingBar from "My dirty little secret from Reason 3. ControlTemplates" it's as easy as specifying the cell's template using a good old DataTemplate:

<GridViewColumn Header="Customer Rating">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <src:RatingBar Template="{StaticResource ratingBarTemplate}"
                         Maximum="5" Value="{Binding CustomerRating}"
                         Width="100" Height="20" />
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

Basic List View showing the RatingBar

Neat. But what else can it do?

In two recent posts (Binding to the Current Item and How binding to the Current Item works) I discussed how, when binding to a collection in WPF for any type of ItemsControl, an underlying CollectionViewSource is created and this can be reached using CollectionViewSource.GetDefaultView(object source). This returns an implemetation of the ICollectionView interface which has two properties I want to look at: SortDescriptions and GroupDescriptions.

SortDescriptions

You've probably guessed by now that the SortDescriptions property allows me to sort my collection. Bingo, and it's as easy as this:

ICollectionView icv = CollectionViewSource.GetDefaultView(_books);
icv.SortDescriptions.Add(new SortDescription("Author", ListSortDirection.Ascending));

I don't really need to explain that - suffice to point out that performing a sort changes the order that items appear in the ListView. In fact, I've talked about this in more detail in my post about creating a Sortable ListView where we used Attached Properties and the natural extensibility of WPF to create a SortableListView control that will automatically sort items when the user clicks the column header.

GroupDescriptions

Again, you've probably guessed that the GroupDescriptions property has something to do with the grouping of items and you'd be right. Programmatically it's just as easy to group an ICollectionView:

ICollectionView icv = CollectionViewSource.GetDefaultView(_books);
icv.GroupDescriptions.Add(new PropertyGroupDescription("CustomerRating"));

However, doing this alone will have no impact on your GridView based ListView. We need to specify what the grouping should look like and we call on our old friend the ControlTemplate here.

<ListView x:Name="_lstBooks" Grid.Row="1" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True">
    <ListView.GroupStyle>
        <GroupStyle>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Margin" Value="0,0,0,5"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <Expander IsExpanded="True" BorderBrush="Black" BorderThickness="0,0,0,1" Background="Navy">
                                    <Expander.Header>
                                        <TextBlock Foreground="White">
                                            <Run>Customer Rating: </Run>
                                                <TextBlock FontWeight="Bold"
                                                Text="{Binding Path=Name}" />
                                                <TextBlock Text=" ("/>
                                                <TextBlock
                                                Text="{Binding Path=ItemCount}"/>
                                                <TextBlock Text=" items)" />
                                        </TextBlock>
                                    </Expander.Header>
                                    <Expander.Content>
                                        <Border Background="White" Margin="2" CornerRadius="3">
                                            <ItemsPresenter />
                                        </Border>
                                    </Expander.Content>
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </ListView.GroupStyle>
    ...
</ListView>

Basic List View showing the RatingBar

As you can see, grouping now works a treat and we've wrapped each group in an Expander control. Why not have a play with the Reason 7 ClickOnce sample to see for yourself.

Tags: WPF

 
Josh Post By Josh Twist
10:30 AM
17 Nov 2007

» Next Post: Silverlight to get full WPF databinding honors
« Previous Post: How binding to the Current Item works

Comments are closed for this post.

Posted by Henrik @ 19 Nov 2007 12:43 AM
Great series of WPF posts, please add more..

Posted by David @ 23 Jan 2008 2:23 PM
When I view almost any WPF application, including the click once application from this post, the text is blurry. I have wanted to start using WPF for a while, but if reading the text (a pretty important thing in most of the applications I design) makes my eyes hurt, I'm not likely to pick it up soon. Have you ever encountered this, and do you have any idea what the problem is?

Posted by Josh @ 26 Jan 2008 4:42 AM
Crikey David, have you just read this whole blog in a day? Thanks for taking the time to comment tho'

I'm not sure what you mean. The screenshots shown here are actual shots of the WPF app - the text is no blurrier than when you have cleartype enabled (which I do). Do you think that text is blurry?

Text will blur in WPF sometimes during an animation or for a split second after a transform but I've had no problems otherwise.

Posted by David @ 27 Jan 2008 10:47 PM
Not the whole blog no :) A WPF-ophile friend of mine pointed me to your 10 reasons. He has been trying to persuade me to take the plunge. I have seen a number of impressive things, but I am still not convinced it is worth the effort to climb the learning curve just yet.

About the blurry text - no, the text in your screenshots is not blurry. But when I run the app on my system (with ClearType on), it is. I will try to send you a screenshot.

Posted by Per Gunnar @ 28 Mar 2008 5:54 AM
ClearType is only for modern flat screens, and does not work in all cases. You can read more about it on Wikipedia.

Posted by raffaeu @ 08 Jun 2009 1:06 PM
Great sample especially for the grouping!

Posted by Ed @ 12 Aug 2010 3:16 PM
Yes, surely an WPF app can look good. And you can easily do thinks that are too hard with other approachs. Thats the most that I can say about WPF.
On the other hand, you need converters to format columns (!!!) even to align a number, you need to add an "x:" to a control's name just because it is defined in the same assembly (!?!?)... I could continue with more and more.

Now I am surprised that you need to work so hard to sort a ListView. Come on! The data is loaded, the columns have values, most of the values could have a default logic for sorting... but with WTF you have to do everything from zero to implement any sorting.

Yes, WPF has a lot of fresh and good ideas (user point of view is welcome), but people is overvaluating things that were solved before and now suck with WTF.

For now, I call it WTF instead of WPF

Posted by Ed @ 06 Sep 2010 4:58 PM
Here I have a little list of things that could be a real pain if you decide to use WTF:

1- Right align for numbers inside a Listview
2- Set focus on a Control of a UserControl
3- Show a description instead of a key on a Listview column
4- Iterate through the Listview "cells" to read values
5- Listview sort on a header's column click
6- Restrict the user entry inside a Textbox
7- Properly edit a Date field
8- Change the UI and app's thread culture

I mean, some simple things are weirdly complicated, while the "cool ones" are outstanding.

Posted by Josh @ 06 Sep 2010 6:20 PM
Are you sure all of those are tricky? I don't have time to test each but many of them sound reasonably straightforward. For example, I posted here some time ago about one easy way to add sorting to your ListViews: http://www.thejoyofcode.com/sortable_listview_in_wpf.aspx

Also, WPF has come a long way since I wrote this series.

Posted by Steve @ 23 Sep 2010 4:31 PM
This is great stuff! I have a different scenario for Listview I've been unable to solve & wondering if anyone has come across this:
I would like a Listview that contains a Gridview, but with each row containing an expander in the 1st column which when clicked opens a user control directly below the row and stretches across the listview spanning any number of columns. I have done this successfully with the new accordion control but it doesn't have any column headers for sorting & resizing the columns. Any solutions for this would be very welcome!

Posted by Anthony @ 31 Jan 2011 3:38 AM
Hello, I have been looking all day for a sample close to your grouped list box with multiple columns (Reason #7 - List View) but having a hard time piecing together your code to simulate it against my data. Seems not all the code is there.

Do you have the full solution you could share? That would be very helpful. thanks..

Posted by Anthony @ 31 Jan 2011 3:41 AM
For example, the XAML for the listview does not seem to be producing the gridview style as i see no column definitions..

Posted by Deeks @ 08 Sep 2011 12:47 AM
I have to agree with Ed, when did grouping and sorting become such a chore? I have been working as a programmer nearly 20yrs and now all this XAML and extra code and cryptic referencing just for some eye candy? I am struggling to see the point. I will put money on it that if WPF survives you will see MS come out with simpler cleaner versions of it until its where it should be.

© 2005 - 2014 Josh Twist - All Rights Reserved.