Filtering collections from XAML using CollectionViewSource

by Nico 12. April 2012 17:18

I find that I often run into the need of separating a collection of items into several collections just so I can bind them to multiple listboxes, for example a list of sessions spanning several tracks and each track is shown in his own listbox in a pivotitem. To get this done you can start by adding multiple collections to your viewmodel and divide the items there. However this makes your viewmodel very big in a very short time. A better way to do this is using CollectionViewSource items in XAML. Let me show you how.

First thing I did was building a demo class existing out of a title and a description, these two properties will be shown in the listbox later on. A third property is the one we’ll use to filter the data, here’s the completed class.

public class DemoClass
{
    public string Title { get; set; }
    public string Description { get; set; }
    public Pivot PivotToAppearIn { get; set; }
}

Nothing special here. Notice the Pivot instance, this is just an Enum that will be the way to filter later on.

public enum Pivot
{
    First,
    Second,
    All
}

For the demo’s purpose I’ll be creating a bunch of dummy data in the viewmodel. The project template I’ve used here is the default pivot app template in the Windows Phone 7.1.1 SDK. It comes with a bunch of dummy data, I’ve used the same data but put them in instances of the DemoClass. Those instances are put inside an ObservableCollection.

This is the viewmodel

public class MainViewModel : INotifyPropertyChanged
{
    public const string ItemsPropertyName = "Items";
    private ObservableCollection<DemoClass> items;
    public ObservableCollection<DemoClass> Items
    {
        get
        {
            return items;
        }

        set
        {
            if (items == value)
            {
                return;
            }

            items = value;
            NotifyPropertyChanged(ItemsPropertyName);
        }
    }

    public MainViewModel()
    {
        this.Items = new ObservableCollection<DemoClass>();
        LoadData();
    }

    public void LoadData()
    {
        Items.Add(new DemoClass 
        { 
            Title = "runtime one", 
            Description = "Maecenas praesent accumsan bibendum", 
            PivotToAppearIn = Pivot.First 
        });
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

So we’ve got our basic bindable property here and a method that loads in the dummy data. In the demo project there’s obviously more then one item in the collection, there’s about 16 to be precise.

In the design I didn’t change a lot from the default template. I’ve just copied the ItemTemplate from the listbox to the pageresources so that it can be reused in the second listbox.

This is the template.

<phone:PhoneApplicationPage.Resources>
    <!-- template for the listboxes -->
    <DataTemplate x:Name="ListBoxTemplate">
            <StackPanel Margin="0,0,0,17" Width="432" Height="78">
                <TextBlock Text="{Binding Title}" TextWrapping="Wrap" 
                           Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                <TextBlock Text="{Binding Description}" TextWrapping="Wrap" 
                           Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
            </StackPanel>
        </DataTemplate>
</phone:PhoneApplicationPage.Resources>

All right now that the preparations are set, time to get into the filtering. First step is to add a CollectionViewSource for each listbox. These are set on the same place as I’ve put the listbox ItemTemplate, in the pageresources. For this demo I need two CollectionViewSources.

<CollectionViewSource x:Name="FirstPivot" Filter="FirstPivot_Filter" Source="{Binding Items}" />
<CollectionViewSource x:Name="SecondPivot" Filter="SecondPivot_Filter" Source="{Binding Items}" />

So what’s all this? x:Name is like in any other XAML object, it’s just the name that can be used to reference the object. The source is the ObservableCollection that was created in the viewmodel. And last but definitely not least is the Filter event. This event will fire for every item in the collection that is bound to the Source property.

Now for the event handler, I’ll just post the event handler FirstPivot_Filter here because they are basically the same.

private void FirstPivot_Filter(object sender, System.Windows.Data.FilterEventArgs e)
{
    e.Accepted = (e.Item as DemoClass).PivotToAppearIn == Model.Pivot.First || 
        (e.Item as DemoClass).PivotToAppearIn == Model.Pivot.All;
}

FilterEventArgs has two properties, Accepted is a boolean that when true shows the item in the listbox that is bound to the CollectionViewSource. Item is the current item in the collection. Remember that this event is triggered for each item in the collection. So what we do here is casting the Item property to an instance of DemoClass then check if the PivotToAppearIn property, that was an instance of the enum, is either First or All.

Now that we have the CollectionViewSources and the event handlers in place it’s time to bind the ViewSource to the listbox.

<controls:PivotItem Header="first">
    <ListBox x:Name="FirstListBox" Margin="0,0,-12,0" 
             ItemsSource="{Binding Source={StaticResource FirstPivot}}"
             ItemTemplate="{StaticResource ListBoxTemplate}" />
</controls:PivotItem>

The bindingsource of ItemsSource is bound to the CollectionViewSource that filters for this listbox. And that’s it!

 

In this article I’ve shown how you can filter a collection using a CollectionViewSource in XAML. This is an easy and fast way to visually filter data while keeping a clean ViewModel.

Download the Demo project here.

Tags:

.Net | Binding | MVVM Light | Windows 8 | XAML | WP7 | WP8 | Silverlight | Metro | Devices

Techdays Belgium 2012

by Nico 2. February 2012 08:27

So Techdays is right around the corner and I’ll be attending for the third time.I’ll be attending all kinds of sessions going from Windows 8 development to the complete deep dive track on web to my favorite subject, Windows Phone 7 development. I’m also excited about the Scott “The Gu” Guthrie doing the opening keynote and doing a session the second day. Also presenting this year is Laurent Bugnion, the father of the awesome MVVM Light framework.

Here’s the list of sessions I’ll be attending, this list is subject to change depending on if I change my mind the last minute, as I’m known to do sometimes Glimlach.

Tuesday February 14th

  • Opening keynote with Scott Guthrie
  • Welcome to the Metro Application Platform
  • Windows Phone Fast App Switching, Tombstoning and Multitasking
  • The Future of C# and Visual Basic
  • Devices + Cloud: Using Azure on iOS, Android, Windows Phone, …

Wednesday February 15th

  • ScottGu unplugged
  • Take a ride on the Metro
  • The zen of async: Best practices for best performance
  • MVVM Applied: From Silverlight to Windows Phone to Windows 8
  • MVVM & WCF RIA Services: an architectural story
  • Building a data intensive application

Thursday February 16th

This is a deep dive day, I’ll be following the web track that focuses on what’s new in ASP.net 4.5 and Visual Studio 11

 

Tags:

.Net | Presenting | WP7 | Windows programming | XAML | XNA | Web development | MVVM Light | Devices

Comic Organizer Part III: MainViewModel and Facade pattern

by Nico 21. October 2011 19:56

Last time we did some Xaml work to setup the metro style that will be used throughout the application, now it’s time to dive into some C# code. In this part we’ll start adding some properties to the MainViewModel that can be used for databinding and we’ll talk a bit about the Façade pattern, the first of the design patterns that we’ll try to implement.

 

ViewModel

To show data in the views of an MVVM application we need some bindable properties. Those properties are called bindable because they can be bound to a control on the view, for example a string property can be bound to a textbox so that the value of the string is shown as the textbox.Text property. Or the other way around, or both ways. Creating those properties works in the same way you’d create a property in any class but they can’t be auto properties, you need to create them the old-fashioned way. For the moment I need two properties, a string that will contain the text that a user typed into the searchbox and a list that will contain the searchresults.

Code Snippet
  1. private string searchString;
  2. public string SearchString
  3. {
  4.     get { return searchString; }
  5.     set
  6.     {
  7.         searchString = value;
  8.         RaisePropertyChanged(SearchStringPropertyName);
  9.     }
  10. }
  11.  
  12. private Response searchResult;
  13. public Response SearchResult
  14. {
  15.     get { return searchResult; }
  16.     set
  17.     {
  18.         searchResult = value;
  19.         RaisePropertyChanged(SearchResultPropertyName);
  20.     }
  21. }

“Wait, I thought you said one of them would be a list?”
Yes I did
“But I see no list”
Deceiving looks can be my young Padawan.

“Response” is a class I build that contains the list I previously mentioned, it’s in a separate class so that later on I can use the MVVM Light messenger to pass it around, the messenger won’t pass around a list so this is a work-around, more about that when we get to that.

 

Domain Project

The response classed is declared in a separate project, I’ve added a C# class library to the solution and called it “ComicOrganizer.Domain”. It will contain all the classes I’ll be needing, for now it just contains the Response class

The Response class looks like this:

Code Snippet
  1. public class Response
  2. {
  3.     public int NumberOfPageResults { get; set; }
  4.     public int StatusCode { get; set; }
  5.     public string Error { get; set; }
  6.     public IList<SearchResult> Results { get; set; }
  7.     public int Limit { get; set; }
  8.     public int Offset { get; set; }
  9.     public int NumberOfTotalResults { get; set; }
  10. }

So it has a few more properties than just a list, but we’ll need them later. These can be auto properties because we won’t be binding them to a control in the view.

The application will be using a normal List<T> but I’ve declared it here as an IList<T> so that, if we in the future build our own list, based on IList<T> we won’t need to adapt our class. Working with interfaces instead of implementations is also a best practice and helps utilising the Open/Close principle.

The IList expects members of type “SearchResult”, which is also one of my homecooked classes. A small background before we dive into that one. The purpose here is to accept a searchstring by the user, send the string to the Comicvine api, which returns the result as a JSON object (more about that later). We deserialize the JSON object in objects that our application can understand and pass it to the ViewModel. A JSON result returned by ComicVine looks like the Response class above, it states how many pages it contains (20 items per page), it has a StatusCode which is 0 if everything went peachy, if it hasn’t it sends the error. It has an array with 20 results, a total results and an Offset. With the offset we can ask the API for results 0-20 or 20-40 and so on.

The results themselves look like the SearchResult class I’ve build:

Code Snippet
  1. public class SearchResult : IResource
  2. {
  3.     public Publisher PublishedBy { get; set; }
  4.     public Image Images { get; set; }
  5.     public string Name { get; set; }
  6.     public string ApiDetailUrl { get; set; }
  7. }

As you can see this class implements the IResource interface, which is just an empty interface, the use will become clear later on. Also the Image type used here isn’t the .net Image type, it’s again a custom class, just like Publisher.

Code Snippet
  1. public class Image : IResource
  2. {
  3.     public string IconUrl { get; set; }
  4.     public string MediumUrl { get; set; }
  5.     public string TinyUrl { get; set; }
  6.     public string SmallUrl { get; set; }
  7.     public string ThumbUrl { get; set; }
  8.     public string ScreenUrl { get; set; }
  9.     public string SuperUrl { get; set; }
  10. }
  11.  
  12. public class Publisher : IResource
  13.     {
  14.     public string LocationCity { get; set; }
  15.     public string LocationState { get; set; }
  16.     public string LocationAddress { get; set; }
  17. }

And that’s all the classes we need for now. The returned JSON contains a whole lot more information but we won’t be using that, so we filter it out.

 

Facade Pattern

The Façade Pattern according to dofactory.com:

Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.

The façade pattern creates some sort of API on top of an API, there are many reasons to do so. In our case it’s because the Comicvine API is very big and we only need a portion of it, also the Comicvine API returns JSON results, we need .net objects. So we create a wrapper around it, this wrapper is called the Façade pattern.

I’m going to start with just one method in the façade pattern, we will expand it as this series moves along. For starters I created an interface called IApi, the interface has one method called SearchVolume. This will search the Comicvine database for all comic series (called Volumes by Comicvine) that contain the searchstring the user entered. The interface looks like this:

Code Snippet
  1. public interface IApi
  2. {
  3.     void SearchVolume(string searchString);
  4. }

It accepts the searchstring but doesn’t return any value because getting the info will happen asynchronously and we will return the result by using the MVVM Light Messenger.

Now, why would I want to use an interface for my façade pattern? Let’s say that in a few months I run against another comicsite that offers an api that I want to include in my application. I can just build a second façade that again implements the interface but talks to the new API. I don’t have to adjust any logic in my view or viewmodel because it uses all the same methods and returns the same types, pretty cool huh?

Okay, let’s implement the interface in a class called ComicVineApi

Code Snippet
  1. public class ComicVineApi : IApi
  2. {
  3.     public void SearchVolume(string searchString)
  4.     {
  5.         string completeUrl = ComicVineConstants.Url + "search/" + ComicVineConstants.Key + "&query=" + searchString + "&resources=volume" + "&field_list=" + ComicVineConstants.VolumeFields + ComicVineConstants.Format;
  6.  
  7.         Download(completeUrl);
  8.     }
  9.  
  10.     private void Download(string url)
  11.     {
  12.         WebClient client = new WebClient();
  13.         client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(ClientDownloadDetailStringCompleted);
  14.         client.DownloadStringAsync(new Uri(url));
  15.     }
  16.  
  17.     private void ClientDownloadDetailStringCompleted(object sender, DownloadStringCompletedEventArgs e)
  18.     {
  19.         if (e.Error == null && !e.Cancelled)
  20.         {
  21.             JsonSerializer jsonrep = new JsonSerializer();
  22.  
  23.             string json = e.Result;
  24.             Response response = new Response();
  25.  
  26.             response = jsonrep.ConvertJson(json);
  27.  
  28.             Messenger.Default.Send<Response>(response);
  29.         }
  30.         else
  31.         {
  32.             MessageBox.Show(e.Error.Message);
  33.         }
  34.     }
  35. }

So what happens here? In the SearchVolume method we build the url that contains the Comicvine API request. a complete url looks like this:

http://api.comicvine.com/search/?api_key=1234f&query=hulk&resources=volume&field_list=api_detail_url,count_of_issues,description,
image,name,start_year,site_detail_url&format=json

I removed my API key from the URL for obvious reasons, if you want to test this link out you can request your own API key at http://www.comicvine.com it’s completely free.

The ComicVineConstants is a class where I put most of my so called magic strings, strings hard coded in the application.

Code Snippet
  1. public class ComicVineConstants
  2. {
  3.     public const string VolumeFields = "api_detail_url,count_of_issues,description,image,name,start_year,site_detail_url";
  4.     public const string Key = "?api_key=1234";
  5.     public const string Url = "http://api.comicvine.com/";
  6.     public const string Format = "&format=json";
  7. }

Again, the API key is removed from this code for obvious reasons.

So once the url is build it’s passed into the download method which will start an asynchronous download by using a WebClient instance. After that the application continues to run while the JSON results are downloaded on the background, once the download is complete the DownloadStringCompletedEventHandler will fire. The eventhandler deserialises the JSON into .net objects by using JSON.net, which is available on NuGet, and sends it on it’s way.

The Messenger class is part of the Galasoft.MvvmLight.Messaging assembly. In the eventhandler we say that we want to send an object of type “Response” on the instance called “Default” of the Messenger class. Now every class that has registered to messages of type “Response” will receive the message and can act accordingly. The Messenger class helps the separation of concerns here by allowing us to send the result to any instance of any class available, without it we would have to do the download logic in the ViewModel and that just feels plain wrong.

I will end this part here. In part IV we will start building some UI, do some databinding and register our MainViewModel to the Messenger class. And we will finally start receiving some data from the Comicvine API so we can see our façade pattern in action, until then: Live long and prosper!

Tags:

.Net | WPF | Patterns | MVVM Light

About the author

Hi,

My name is Nico, I’m an MCP living in Belgium.
I’m currently employed as a .Net Software Developer at RealDolmen, one of Belgium’s leading IT single source providers.

I'm also founding member and board member of the Belgian Windows Phone User Group. If you're in Belgium feel free to drop by if we're doing an event. http://www.wiphug.be

This blog will be about Windows Phone 7, C#, XNA , WPF, Silverlight, and much more!

I hope to get feedback from my readers either through comments, mail (nico_vermeir@hotmail.com), twitter, facebook, …

 

Month List