(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

ClassifiedCabinet: A Quick Start

(9 votes)
>
Georgi Stoyanov
Joined Feb 24, 2011
Articles:   1
Comments:   9
More Articles
30 comments   /   posted on Mar 02, 2011
Categories:   Line-of-Business , General , Controls

Introduction

The aim of this article is to serve as a short introduction to the new ClassifiedCabinet control published on codeplex. I tried to give you everything that is necessary to start using the control, without going into too much detail. I’ll be building a very simple project from scratch that should demonstrate the basic usage of the control. Of course, the source code of the sample is available for download. By the way here is a live demo of what we want to achieve:

View sample live demo

Download sample source code

Set Up the Project

OK, so let’s get started. First we need to create a new Silverlight project. I’ve called it “ClassifiedCabinetDemo”. Then you need to add a reference to the CompletIT.Windows.Controls.ClassifiedCabinet.dll. To keep things as simple as possible, I just copied the file to the “Debug” folder of the demo project and added the reference from there. Now you can just go to the MainPage.xaml, add the CompletIT.Windows.Controls namespace from the CompletIT.Windows.Controls.ClassifiedCabinet assembly and start using the control right away.

<UserControl x:Class="ClassifiedCabinetDemo.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:completITControls="clr-namespace:CompletIT.Windows.Controls;assembly=CompletIT.Windows.Controls.ClassifiedCabinet"
             mc:Ignorable="d"
             d:DesignHeight="600"
             d:DesignWidth="900">
 
    <Grid x:Name="LayoutRoot"
          Background="White">
 
        <completITControls:ClassifiedCabinet Width="900"
                                             Height="600" />
    </Grid>
</UserControl>

This is the code of the MainPage.xaml so far. I’ve added the xml namespace and the ClassifiedCabinet control itself. However, this is what it looks like:

It seems we’ll need some extra work to make it do something useful, since right now the control is just notifying the user that there is nothing to display. It’s not very impressive, isn’t it? Well, let’s give it some actual data to display and see what happens.

Adding the Categories

I have created an object to hold all the data we need and set it as the page’s data context, so we can just bind the necessary properties. First you need to set the CategoriesItemsSource. As its name suggests, it is a collection containing the categories. After giving the the ClassifiedCabinet control its categories, you’ll need to tell it how to display them. Basically, you have the standard means to do so – you have an option to set the path to a member to display using CategoriesDisplayMemberPath or if you need something more complicated you can change the whole DataTemplate using the CategoriesItemTemplate property. And just a quick note - as it is the case with other such controls, you can’t use both at the same time as it makes no sense, so just choose whatever seems more appropriate. There are other properties that allow you to fine-tune the look-and-feel of the categories section, but I shall look at these in some of the next articles, so we can keep this quick start really quick. For now it is enough to say that they’re all prefixed with “Categories” and have pretty intuitive names, so if you want you can go ahead and play with the control a little to discover them. Actually, we are going to use one more property now – CategoriesWidth, but I think you can all figure out what it does. Let’s see what we have got so far:

<completITControls:ClassifiedCabinet Width="900"
                                     Height="600"
                                     CategoriesItemsSource="{Binding Categories}"
                                     CategoriesDisplayMemberPath="Name"
                                     CategoriesWidth="250" />

As you can see the main page’s data context has a property called Categories which is basically a collection of Category objects. Right now every category has just a name and that’s what we are using to display it. Let’s see what we have done:

The categories section is ready and it looks kind of nice, doesn’t it? However, the items section is still empty – no shelves yet. OK, let’s see what we can do about it.

Adding the Items

Well, no surprises here. We have an ItemsSource property that we can use to give the ClassifiedCabinet its items. Of course, we’ll need to define an appropriate data template to tell it, how we want it to visualize them, so there is an ItemTemplate property as well. I have bound the ItemsSource property to a collection of Book objects in my data context. The Book object is very simple – it has just a Title, Author, PublishDate and Description properties that are all of type string for simplicity. My DataTemplate for this book is just a border and a TextBlock with the book’s title – nothing fancy. Here it is:

<DataTemplate x:Key="ClassifiedCabinetItemTemplate">
    <Border Background="DeepSkyBlue"
            BorderBrush="DodgerBlue"
            BorderThickness="3"
            Width="150"
            Height="200">
        <TextBlock Text="{Binding Title}"
                   TextAlignment="Center"
                   VerticalAlignment="Center"
                   FontFamily="Verdana"
                   Foreground="White"
                   FontSize="14"
                   Margin="10"
                   TextWrapping="Wrap" />
    </Border>
</DataTemplate>

And that’s all. You can now run the project and you’ll have all the shelves populated and the ClassifiedCabinet has even added appropriate labels to every shelf. You can also zoom and move around with the mouse – isn’t it cool?

However, we are not done, yet. There are few more things we need to take care of. You may have noticed that the books are not associated with particular categories, but instead the cabinet seems to have placed all the books on every shelf. Well, that is perfectly normal, since we haven’t yet told it how we want it to “classify” them. However, we’ll do this in the next section, while now we’ll look at something else that appears to be missing. If you click on an item in the cabinet, you get a fancy dialog that contains …nothing. Luckily, there is a property for that. It’s called ItemDetailsTemplate and it is another DataTemplate for the book that’s expected to give more details about it and is used to present the item in the dialog. You may have noticed that the book data class has four properties, but we are using only one of them. Well, now we’ll be adding the rest three. So the idea is that the DataContext for both DataTemplates is the same – an object from the collection you bind the cabinet’s ItemsSource to (in our case a Book), but you define two data templates – one to be used while the item is on the shelf and another, when the user clicked on the item and opened the dialog to see something more about a particular item. By the way, while the author and publish date are correct, the description of the book is always the same lorem-ipsum – I didn’t want to have too much sample data in the project. Finally, here’s our template for the dialog:

<DataTemplate x:Key="ClassifiedCabinetItemDetailsTemplate">
            <Grid Margin="15">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
 
                <TextBlock Grid.Row="0"
                           FontSize="18"
                           TextWrapping="Wrap"
                           Text="{Binding Title}" />
 
                <TextBlock Grid.Row="1"
                           FontSize="12"
                           FontStyle="Italic"
                           Text="{Binding Author, StringFormat='By \{0}'}" />
 
                <TextBlock Grid.Row="2"
                           FontSize="12"
                           FontStyle="Italic"
                           Text="{Binding PublishDate, StringFormat='Released on \{0}'}" />
 
                <TextBlock Grid.Row="3"
                           FontSize="12"
                           Margin="15"
                           TextWrapping="Wrap"
                           Text="{Binding Description}" />
            </Grid>
        </DataTemplate>

Here’s how it looks in action:

OK, so that’s all you need to add the items to the cabinet. However, they are not classified as we have already mentioned. We wanted different items in the different categories, right? Let’s see how it is done.

Classifying the Items

Basically, it’s really easy - you only have to set a property called ClassifierFunc, which is a function that controls the whole process. The property is of type Func<object, IEnumerable, IEnumerable>, so this is a function that takes an object and an enumeration as arguments and returns another enumeration. In fact, here’s the signature of the function to make it more clear:

public IEnumerable Classify(object category, IEnumerable items);
Now the ClassifiedCabinet will call the function every time you change its ItemsSource or CategoriesItemsSource changes, to classify the items. The first argument is the category object and you can safely cast it to the type of your category. The second is an enumeration containing the items that have to be classified. Note that it doesn’t necessary contain all the items. The function has to return another enumeration that contains just these items that belong to the specified category. In a sense, it filters the items according to provided category. Here’s an example:
public IEnumerable Classify( object category, IEnumerable books )
{
    return books.Cast<Book>().Where( book => book.Category == category );
}

It’s quite simple, isn’t? I added a property Category to the Book class and I just return the books that say they belong to the category in question. In reality, you may want to associate a book with more than one category. This is easy as well, but for the sake of simplicity we’ll stick to the one-category version in this example. Having the function defined like this, now you need a property that wraps the function for use in binding. The type of the property, of course has to be Func<object, IEnumerable, IEnumerable>. Once you bind the ClassifierFunc property of the ClassifiedCabinet to the newly defined property on the data context, you have it all set up.

 

So what’s left? Well, not much actually, we are almost done. The only thing that still doesn’t work is the filter that’s located on top of the categories.

Filtering the items

The filtering is actually quite similar to the classifying. In fact, the only difference is that the filtering function receives the current input from the user instead of the category as a first argument and should return the items that pass this filter according to its custom logic. In our case we want to return all books that contain the user input, either in the title or in the author fields. We are performing a case-insensitive search. Here’s the code of the function, along with its property wrapper required for data-binding:

public Func<string, IEnumerable, IEnumerable> FilterFunc
{
    get
    {
        return this.Filter;
    }
}
 
private IEnumerable Filter( string userInput, IEnumerable books )
{
    string uppercaseUserInput = userInput.ToUpper( CultureInfo.CurrentUICulture );
 
    return books.Cast<Book>().Where( book =>
        book.Title.ToUpper( CultureInfo.CurrentUICulture ).Contains( uppercaseUserInput ) ||
        book.Author.ToUpper( CultureInfo.CurrentUICulture ).Contains( uppercaseUserInput ) );
}

After you bind the actual property of the control, you can run the project and test the filtering functionality of the ClassifiedCabinet. For example I have typed ‘game’ and here’s what I got:

As you can see there are only three books on this topic right now. Also the shelves that don’t have any books related to the search have disappeared and their respective categories in the categories menu are now disabled. Just in case, let’s add post the final version of the xaml:

<completITControls:ClassifiedCabinet Width="900"
                                     Height="600"
                                     CategoriesItemsSource="{Binding Categories}"
                                     CategoriesDisplayMemberPath="Name"
                                     CategoriesWidth="250"
                                     ItemsSource="{Binding Items}"
                                     ItemTemplate="{StaticResource ClassifiedCabinetItemTemplate}"
                                     ItemDetailsTemplate="{StaticResource ClassifiedCabinetItemDetailsTemplate}"
                                     ClassifierFunc="{Binding ClassifierFunc}"
                                     FilterFunc="{Binding FilterFunc}" />

Conclusion

Well, that is all you need to start using the ClassifiedCabinet control. As you can imagine, it’s quite a huge control that has a lot of options, supports a lot of different scenarios and with little imagination can be used in a lot of different situations.

Since this was intended as a short introductory article, there is a lot of things left and I’ll be writing a few more articles to cover some of the more advanced usages of the classified cabinet, but I hope that this’ll be enough to get you all started.

Also I hope you like the control. I think it’s really cool and can do a lot of things, but I ‘m really looking forward to getting some actual feedback and I’ll be interested to know what you think about it.


Subscribe

Comments

  • -_-

    RE: ClassifiedCabinet: A Quick Start


    posted by David on Mar 07, 2011 09:13

    Hi,

    Have you ever heard about Microsoft PivotViewer?

    David

  • -_-

    RE: ClassifiedCabinet: A Quick Start


    posted by Shawn Wildermuth on Mar 10, 2011 01:20
    Any plans for a WP7 version? 
  • emil

    RE: ClassifiedCabinet: A Quick Start


    posted by emil on Mar 10, 2011 09:17

    @David, the classified cabinet is much more targeted solution and you have more control over the way items are generated, the way user browse through the items, the details view can be completely styled, etc.

    @Shawn, yes, WP7 version is on its way, but keep that secret :-) I would love to hear your feedback on this - what scenarios do you target on WP7?

  • -_-

    RE: ClassifiedCabinet: A Quick Start


    posted by Flavio on May 25, 2011 17:48

    I also could be pursuing a WP7 app ... I see a basic scenario where the WP7 devices feeds a PC shelf but keeps a small repository "TO AVOID BUYIG AGAIN THE SAME BOOK YOU ALREADY HAVE".

    I put more enphasis on how to use barcoding and ISBN web services to get basic data in than how to show it.

    Flavio

  • arkgroup

    Re: ClassifiedCabinet: A Quick Start


    posted by arkgroup on Jun 22, 2011 20:56

    I need to add link for every book and show it with Detail popup window. How can I do that?

    Thanks

     

  • Re: ClassifiedCabinet: A Quick Start


    posted by GStoyanov on Jun 23, 2011 11:36

    @arkgroup

    I'm not sure I understand. Could you explain a bit more what you are trying to accomplish? Where do you want to add the link? Could you perhaps give me an example?

  • arkgroup

    Re: ClassifiedCabinet: A Quick Start


    posted by arkgroup on Jun 23, 2011 14:28

    When you click on book image showing on shelf, you open new window with book Description, Title, Author, PublishDate that stored in book class. I need to add link to that class and show this link in that window. When user click on link it will open new browser.

    Thanks

  • Re: ClassifiedCabinet: A Quick Start


    posted by GStoyanov on Jun 24, 2011 10:25

    @arkgroup

    Basically, you have to add some url property to you 'Book' object - the one you use as the DataContext of this window. Then you should add a HyperlinkButton element to the xaml of the window's DataTemplate and bind its NavigateUri to your property - NavigateUri="{Binding NameOfUrlProperty}".

    If you are looking at the sample at http://classifiedcabinet.codeplex.com/, than the object that serves as a DataContext to the window is the Book class and it already has a TitleUrl property of type string, which you can use as the link. We initially had an example of adding link in the sample - that's why the property is already there. All you have to do is open BookDetailsView.xaml and add an appropriate HyperlinkButton element somewhere in the "LayoutRoot" Grid element (depending on where you actually want the link displayed). For example:

    <HyperlinkButton Style="{StaticResource NormalHyperlinkButtonStyle}"
        Foreground="{StaticResource DarkBlueTextBrush}"
        FontStyle="Italic"
        NavigateUri="{Binding TitleUrl}"
        Content="some appropriate content" />

    I hope this helps!

  • ManavKumar

    Re: ClassifiedCabinet: A Quick Start


    posted by ManavKumar on Jun 27, 2011 14:40

    HI GStoyanov i m new in silverlight Classified cabinet is amazing.

    i developed a demo project but not able bind data. i tried sample code of codeplex but its very complicated.

    thn i tried to download your sample code, but i m not able to download it. can u please send me sample code on email id manaveyes@gmail.com

    thanks

  • ManavKumar

    Re: ClassifiedCabinet: A Quick Start


    posted by ManavKumar on Jun 27, 2011 14:43
    thanks bro i got ..... 
  • Re: ClassifiedCabinet: A Quick Start


    posted by GStoyanov on Jun 27, 2011 17:28

    Hi Manav Kumar,

    thanks for your feedback. I'm glad you like the control :)

    There is some problem with the link, but you should be able to download the sample if you are already logged in. We will fix it as soon as possible.

  • arkgroup

    Re: ClassifiedCabinet: A Quick Start


    posted by arkgroup on Jun 29, 2011 14:18

    Hi Georgi,

    I downloaded code from codeplex, but still cannot figure out how to add links. Would be possible to modify above sample to include url property? I'll appreciate your help.

    Thank you very much.

     

  • Re: ClassifiedCabinet: A Quick Start


    posted by GStoyanov on Jun 29, 2011 19:21

    Hi arkgroup,

    What is it about these links that you find difficult? Are you having problems with the xaml or the C# part? Try asking a specific question and I'll try to help. I'm not sure if I'll have the time to change the sample just now.

  • khalid.msd

    Re: ClassifiedCabinet: A Quick Start


    posted by khalid.msd on Sep 04, 2011 13:11
    it is a great works , How can we have the category scroll , we have a long list of categories.

    Thanks,
  • Re: ClassifiedCabinet: A Quick Start


    posted by GStoyanov on Sep 07, 2011 14:05

    Hi khalid.msd,

    Thanks for your feedback. I have just uploaded a new version of the ClassifiedCabinet control to Codeplex. It will now add the scrollbar automatically if the content of the categories list doesn’t fit. You should be fine just using the new version.

    Alternatively, if you want to add this behavior yourself or if you want to change something about the scrollbar, you have to edit the CategoriesList template. If you’re using Blend, you can right-click on the ClassifiedCabinet control and choose “Edit Template” -> “Edit a Copy…”. Then in this template you should find the CategoriesList control and do the same operation for it. Now you can edit the CategoriesList or its scrollbars in any way you want.

    Hope this helps

  • khalid.msd

    Re: ClassifiedCabinet: A Quick Start


    posted by khalid.msd on Sep 07, 2011 14:36

    awesome , It works like a charm. Great works keep it up.

    Thanks , 

     

  • Re: ClassifiedCabinet: A Quick Start


    posted by GStoyanov on Sep 07, 2011 16:46

    You're welcome! I'm glad I was able to help

  • khalid.msd

    Re: ClassifiedCabinet: A Quick Start


    posted by khalid.msd on Sep 18, 2011 14:24

    Hi  GStoyanov ,

    Sorry to trouble you again , but it is driving me crazy , I added a store procedure to retrieve more information about the book in the book detail view. I mapped it to a function and I added WebGet method to BookCategoriesDataService.svc , the service working fine from the web browser by accessing it as given below http://localhost:49692/BookCategoriesDataService.svc/GetTableColumn?TableObjectId='271069455084' now how can I display this information in a grid in a bookview detail.

     

    Thanks

  • Re: ClassifiedCabinet: A Quick Start


    posted by GStoyanov on Sep 30, 2011 10:21

    Hi khalid.msd,

    Sorry it took so long to reply. There is an ItemDetailsTemplate property on the ClassifiedCabinet control that is a DataTemplate used for the DetailsWindow. You can think of the DetailsWindow as a ContentControl (it actually inherits from ContentControl, but adds few more things like the window chrome, open/close functionality etc.). Its content is set to the book that is selected or clicked; its ContentTemplate is the value of the ItemDetailsTemplate property. If you need more flexibility, like say changing the chrome, you can use the DetailsWindowStyle property.


  • khalid.msd

    Re: ClassifiedCabinet: A Quick Start


    posted by khalid.msd on Oct 03, 2011 14:13
    Thanks for the great informations
  • liu_meng2000

    Re: ClassifiedCabinet: A Quick Start


    posted by liu_meng2000 on Dec 19, 2011 04:39

    hello,how to set the shelflabel style ,bind data, i want set the CategoriesItemTemplate  contains image and label

  • Re: ClassifiedCabinet: A Quick Start


    posted by GStoyanov on Dec 19, 2011 10:23

    Hi liu_meng2000,

    You can define a DataTemplate and have your image and label there and set CategoriesItemTemplate to this DataTemplate. The DataContext that you can bind to inside the DataTemplate is your category object, i.e. a member of the collection you bind CategoriesItemsSource to. If you feel you need to change the style of the label as well, you can use CategoriesItemContainerStyle or ShelfLabelStyle. The first controls the style of the separate category items to the right, and the second - the orange labels that sit on the shelves. Let me know if you need further help.

    Hope that helps

  • liu_meng2000

    Re: ClassifiedCabinet: A Quick Start


    posted by liu_meng2000 on Dec 22, 2011 11:31

    Hi  GStoyanov ,

    thanks for your infomation,but i have to trouble you again,

    i try,but can't  get it; In fact, http://img5.ph.126.net/-TrZ6wnWS0MVNn6fDq81WQ==/2482327819628432625.jpg 

     this picture of  the link is my want;if you have any  examples,that's very good;

    my email : liu_meng2000@163.com

    thanks very much !

     

     

  • Re: ClassifiedCabinet: A Quick Start


    posted by GStoyanov on Dec 26, 2011 19:20

    Hi liu_meng2000,

    If you want to use the same picture for every item in the menu (i.e. for every category), you can use the CategoriesItemContainerStyle.

    If you're using blend, just edit a copy of the style and add the picture there. If not, you can always find the original style in the source code, copy it by hand, make the changes you need, apply the new style to the control (i.e. set the CategoriesItemContainerStyle property) and you are good to go.

    Cheers!

  • harrycruz

    Re: ClassifiedCabinet: A Quick Start


    posted by harrycruz on Feb 18, 2012 15:51

    Dear Georgi,

    Your control is simply amazing. Congrats.

    I want to programmatically show the details of a specific ShelfItem. How could I do this? My scenario is as follows:

    I needed to add an animation to the ShelfItem template, and after this animation, I need to show the specific books details to the user, in the "Completed" event, wired in the UserControl used as template:

            private void DoubleAnimation_Completed(object sender, EventArgs e)
            {
               DetailsWindow dw = new DetailsWindow();
               
               dw.ShowDialog();

           }

    In short, I needed to replace the have the same Click behavior being launched by the "Completed" event of the animation I attached to the ShelfItem template.

    Could you shed some light on this issue? It's been a couple of days already :)

    Thanks a lot!







  • harrycruz

    Re: ClassifiedCabinet: A Quick Start


    posted by harrycruz on Feb 18, 2012 17:22

    Dear Georgi,

    Your control is simply amazing. Congrats.

    I want to programmatically show the details of a specific ShelfItem. How could I do this? My scenario is as follows:

    I needed to add an animation to the ShelfItem template, and after this animation, I need to show the specific books details to the user, in the "Completed" event, wired in the UserControl used as template:

            private void DoubleAnimation_Completed(object sender, EventArgs e)
            {
               DetailsWindow dw = new DetailsWindow();
               
               dw.ShowDialog();

           }

    In short, I needed to replace the have the same Click behavior being launched by the "Completed" event of the animation I attached to the ShelfItem template.

    Could you shed some light on this issue? It's been a couple of days already :)

    Thanks a lot!







  • VinMc

    Re: ClassifiedCabinet: A Quick Start


    posted by VinMc on Jul 01, 2012 12:03
    hi, i have a problem.
    one category have too many itemsource, so i want to divide more than one shelf.
    can you show me the way to divide one category item and more than one shelf in cabinet?
  • sanjay.s.b.25

    Re: ClassifiedCabinet: A Quick Start


    posted by sanjay.s.b.25 on Aug 23, 2012 10:48

    Hi.. I am trying to use this control in windows application .i.e., WPF application. I copied XAML code from your demo project into my application.

    The changes I did were-

    • I changed "User control" to "Window"
    • Changed namespaces of project names.

    The problem is

    In <Grid> part i.e.,

    <Grid x:Name="LayoutRoot"
              Background="White">
     
            <completITControls:ClassifiedCabinet Width="900"  .... till end

    I am getting error at completITControls:ClassifiedCabinet line, saying "The specified value cannot be assigned to the collection. The following type was expected: "UIElement".    "

     I am new to WPF and SL. Can you please help


  • SagarHinsu

    Re: ClassifiedCabinet: A Quick Start


    posted by SagarHinsu on Feb 01, 2013 21:16

    This help me so much...This is really really helpfull to me...

    Thank you thank you veryy much again...

  • mohitgupta199020

    Re: ClassifiedCabinet: A Quick Start


    posted by mohitgupta199020 on Feb 27, 2014 12:16

    Hey I got this errror while running this code

    Error:-

    Failed to process batch request.

    in MainViewModel.cs

    how to resolve it


Add Comment

Login to comment:
  *      *