Extending the LightSwitch pivotviewer with colored cards and slider based numeric filtering.

Introduction

This post is part of a series. First read http://blog.pragmaswitch.com/?p=441.

We will extend our rudimentary pivot viewer of the first post with card coloring and filtering on numeric values with a slider.

We will use coloring to visualize the movie category (e.g. comedy = red).

We will introduce also a budget value in the movie entity type. We want to be able to filter by means of a kind of slider control.

By the way, when you look to the pivot viewer screen, well… it looks very metro, no? Not bad for a silverlight control, hehe :)

Colored cards

This is the final result we have in mind:

 

How do we achieve this? We want that based on the movie’s category a specific color is used. Furthermore, we would like this to be configurable. In our first implementation the movie entity had a field Category. We will refactor this field into a new table “MovieCategory”, which can carry as well the color used for the category.

Obviously, in order to cope with this change we need to update our method for generating the test data:

    public partial class MoviesListDetail
    {
        partial void AddTestData_Execute()
        {
            //make sure to have the categories
            if (this.DataWorkspace.ApplicationData.MovieCategories.FirstOrDefault() == null)
            {
                    MovieCategory cat = this.DataWorkspace.ApplicationData.MovieCategories.AddNew();
                    cat.CategoryName = "Thriller";
                    cat.DisplayColor = "Blue";
                    cat.CategoryNumber = 1;
                    cat = this.DataWorkspace.ApplicationData.MovieCategories.AddNew();
                    cat.CategoryName = "Comedy";
                    cat.DisplayColor = "Red";
                    cat.CategoryNumber = 2;
                    cat = this.DataWorkspace.ApplicationData.MovieCategories.AddNew();
                    cat.CategoryName = "Children";
                    cat.DisplayColor = "Green";
                    cat.CategoryNumber = 3;
                    cat = this.DataWorkspace.ApplicationData.MovieCategories.AddNew();
                    cat.CategoryName = "Science Fiction";
                    cat.DisplayColor = "Purple";
                    cat.CategoryNumber = 4;
                    cat = this.DataWorkspace.ApplicationData.MovieCategories.AddNew();
                    cat.CategoryName = "Documentary";
                    cat.DisplayColor = "Yellow";
                    cat.CategoryNumber = 5;
                    cat = this.DataWorkspace.ApplicationData.MovieCategories.AddNew();
                    cat.CategoryName = "Musical";
                    cat.DisplayColor = "DarkGray";
                    cat.CategoryNumber = 6;
                    this.DataWorkspace.ApplicationData.SaveChanges();
            }

            int startNumber = 1;

            var lastMovieRecord = this.DataWorkspace.ApplicationData.Movies.OrderByDescending(m => m.Id).FirstOrDefault();
            if (lastMovieRecord != null)
            {
                startNumber = lastMovieRecord.Id + 1;
            }

            Random random = new Random();
            for (int i = startNumber; i <= startNumber + 333; i++)
            {
                Movie newMovie = this.Movies.AddNew();
                int randomCategoryNumber = random.Next(1, 6);
                newMovie.MovieCategory = this.DataWorkspace.ApplicationData.MovieCategories.Where(cat => cat.CategoryNumber == randomCategoryNumber).Single();
                newMovie.ReleaseDate = DateTime.Now.AddDays(-1 * random.Next(3000));
                newMovie.MovieName = "Movie " + i.ToString();
                newMovie.Budget = Convert.ToDecimal(random.Next(100000, 100000000));
            }
            this.Save();
        }
    }

You may notice that we need more code for genering test data than for the actual implementation of the pivotviewer,:)

In order to convert the string present in the movieCategory table, we need a ValueConverter and apply it to the border of our card:

            <pivot:PivotViewer.ItemTemplates>
                <pivot:PivotViewerItemTemplate>
                    <Border Width="300" Height="300" Background="{Binding MovieCategory.DisplayColor, Converter={StaticResource BackgroundConverter}}" >
                        <StackPanel Orientation="Vertical">
                            <TextBlock Text="{Binding MovieName}" 
                            FontSize="30"
                            FontWeight="Bold"
                            Foreground="White"
                            HorizontalAlignment="Center" 
                            VerticalAlignment="Center" />
                            <TextBlock Text="{Binding MovieCategory.CategoryName}" 
                            FontSize="30"
                            FontWeight="Bold"
                            Foreground="White"
                            HorizontalAlignment="Center" 
                            VerticalAlignment="Center" />
                        </StackPanel>
                    </Border>
                </pivot:PivotViewerItemTemplate>
            </pivot:PivotViewer.ItemTemplates>

 

The backgroundconverter implementation is very simple:

public class BackgroundConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string color = value.ToString();

            var xaml = "<SolidColorBrush " +
                "xmlns='http://schemas.microsoft.com/client/2007' " +
                "Color=\"" + color + "\"/>";
            return XamlReader.Load(xaml);
        }

        public object ConvertBack(object value,
                            Type targetType,
                            object parameter,
                            CultureInfo culture)
        {
            return value;
        }
    }

Note that the backgroundconverter would have been much more cumbersome to maintain if we have not stored the color value directly in the MovieGenre table. Now, there is no direct mapping between the category and the color in the converter implementation. As a result the application administrator can choose her favourite color scheme.

 

Filtering on the budget field

The idea is to use a slider to show all movies with a budget larger than the slider value.

This is nothing more than adding a new PivotViewerNumericProperty for the budget field:

 

                <pivot:PivotViewerNumericProperty 
                        Id="Budget" 
                        DisplayName="Movie budget"
                        Options="CanFilter" 
                        Binding="{Binding Budget}"/>
            </pivot:PivotViewer.PivotProperties>

 

As you can see: Simple comme bonjour !

We will cover more in a next post.