Saturday, September 17, 2011

Applying Pageing and Sorting on ListBox Control

Background :
                    If you have ever used the data grid control then you are familiar with the sorting functionality which is provided by default, when you click any of the data grid header then it will sort the records according to the that column name on every click it will sort it ascending or descending direction. Similarly you are familiar with the data pager control which we often used with the data grid control to show record in the form of page which contain specific page size.It was one of the question which one of my colleague ask me "Can we apply paging to the List Box control ". As I didn't use data pager control other then data grid so in this post I have used the data page control and also the sorting which is provided by the PagedCollectionView.

Solution:
                For this example I have the application which you can see in Image 1, Here you can see that I have used combo box control which is used to sort the list box control item in ascending or descending order, List box control to display the records and the data pager control for the paging purpose.

Image 1

The use of paging is very simple it is just same as you do with the data grid control. Just place the data pager control in the xaml and set the Source property of the data pager to the list or collection which is used to bind the list box control, here you can see if I remove the data pager control then it will display all the record of the collection/list as you can see in the Image 2. So paging is quite easy similar to the data grid paging.

Image 2
Second part which is used to sort the items in the list box control is easy as well but you need to do some coding for it. For this I have done some coding in the view model of the home page which you can see in the List 1 here you can see I have posted whole view model as it is small view model not very large amount of coding in it. In the code you can see I have only two properties one is the PersonList (which is of type PagedCollectionView type which is used too bind the list box control ) and second one is the SortDirection property of type string ( which is used to sort the list box item according to the one of the value either ascending  or descending which are display in the combo box as inline items ).

List 1

In the constructor I have populated the PersonList PagedCollectionView by calling GetPersonRecord function of the person class ( the person class has on one property , the name property which is of type string and hold the person name). The main functionality of the sorting is done in the SortDirection property where I have used the SortDescriptions property of the PagedCollectionView to sort the records in the List.SortDescriptions collection of PagedCollectionView describes how items are sorted in view. SortDescriptions is a collection in which we can add more than one sort field. But here in our example as I have only one field which is the name field so I have first clear the SortDescriptions and then add the new sort direction, if you have more then one direction to sort the record then you don't need to call the clear function of the SortDescriptions you just add the new field in that and it will perform the sorting according to the field name which are provided in the list.We add sort field by adding SortDescriptions that specify which property will be used for sorting and the direction(ascending or descending order). When user select Ascending from the combo box then item are sorted from A to Z direction which you can see in the Image 3.

Image 3
When user select Descending from the combo box then item are sorted out from Z to A direction which you can see in the Image 4.

Image 4
I have tried to used the paging and sorting in the list box control and also tried to explain you how you can used it in your code if you have requirement to sort the list box control, you can event it it without giving the control to you user like I have provided the combo box and provided two option ascending and descending. You can download the source code from here.

All and any comments / bugs / suggestions are welcomed!

Friday, September 16, 2011

SelectedItems Using PagedCollectionView Using PropertyChanged

In my post "Get SelectedItems From DataGrid Using MVVM In Silverlight " I have used command and triggers to get the selected items of the datagrid control. Here we will get the selected item of the data grid control without using the command and trigger. Here we will use the PagedCollectionView to get the selected items. So that we can remove the use of the command and the triggers which we have used in the "Get SelectedItems From DataGrid Using MVVM In Silverlight" post and we will take advantage of INotifyPropertyChanged interface.

Solution :
           The solution is very simple as we don't want to use the command and the triggers but we want to achieve this on the property changed which you can achieve by implementing the INotifyPropertyChanged interface. The main page which we are using for this example is shown in the Image 1, here you can see that I have two similar data grid controls on the left side the source data grid control which is populated when the page is loaded and on the right side is the destination data grid control which will display the selected items from the source data grid control.

Image 1

First I would like to discuss the Persons class which I have used for this example which is listed in the List 1. Here you can see that I have inherit the Persons class from the INotifyPropertyChanged interface and also implemented the INotifyPropertyChanged event handler which you can see at the end of the class.I have First name, Last name, city , country and Is selected properties in the class. You can see that I have only raise the PropertyChanged event from the Is selected property as this proper is of type Boolean and I will perform selected of the record based on the true/ false value of IsSelected property. If IsSelected property has value true then record is selected else record is not selected.
List 1

Note: In List 1 I have only shown relevant which I wan to discuss here, function which return sample records has been removed but you can find the function on the sample application which you can download from the link which is provided at the end of the post
In the List 2 you can see the viewModel for the Home page which is used as the data context for the home view.Here you can see that I used two properties one is PersonList which is of type PagedCollectionView and used for the first gird which is place on the left side of the interface and which will be the source datagrid from where you can select record by clicking the check box control which is displayed in the first column of the data grid control.
List 2

Second property which is ObservableCollection type will hold the records for the second datagrid control which is shown on right side and act as destination and will only show records which are selected from the source datagrid and you can only view records in the destination data grid as the check box control property isEnabled is false and IsReady only property of the datagrid is also false. In the constructor I have initialized the PersonList which is of PagedCollectionView type by call the Persons GetPersonRecord function which is the static function and will return List of Persons( which you can find in the Persons class in the downloaded example code). In the next statement I have use foreach loop to attached the PropertyChanged event of the record as I have used the INotifyPropertyChanged interface in the Persons class So  I can now I have PropertyChanged Event for each record.
When you click any of the check box control in the source data grid the PropertyChanged event which is attached with every record and IsSelected property in the Persons class has raise the PropertyChanged event when the value is changed. In Image 2 you can see the sender and the arguments of the events here you can see that in the sender it will show you the whole record and in the arguments it will send the property name which is changed.In the argument 'e' there is name PropertyName which hold the name of the property here you can see that it has "IsSelected" as I have raised the event from IsSelected property.
Image 2

In the PropertyChanged event I have cost the sender to the respective type in this case my class name is "Persons"  so I have created object of type Persons and save the sender in that object. Then in the next statement I have check for the IsSelected value if the value is true then I have added the sender to the SelectedList property which is used to bind to the destination datagrid to show the selected item.

Image 3

When you select records from the source data grid then you can see the selected item in the destination datagrid. For tested purpose I have selected random 3 items from the source data grid and the selected items are shown in the destination data grid as shown in the Image 3 above. If you unchecked the any of the selected record then that record will be removed from the destination datagrid.You can download the source code from here and also test yourself.

Note: In the Persons class you have seen that I have only raised the PropertyChanged event from the IsSelected property because I want to do procession on the basis of the IsSelected property value. If you changed any of the property like First name, Last Name, Country and city then PropertyChanged event will not fires as these properties didn't raise PropertyChanged event in the setter.


All and any comments / bugs / suggestions are welcomed!