Tuesday, July 31, 2012

ListView sorting on column hear clicking


Before sorting


After sorting


********************************************************************************


<Window x:Class="ListViewTutorial.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ListViewTutorial"
        Title="MainWindow"
        Height="350" 
        Width="620" 
        Loaded="Window_Loaded">
    <Window.Resources>
        <!--ListView Styling Start-->
        <LinearGradientBrush x:Key="BackgroundBrush" StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FF6FBDE8" Offset="0"/>
                    <GradientStop Color="#FF4385BE" Offset="1"/>
                </GradientStopCollection>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>


        <LinearGradientBrush x:Key="HighlightBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FF97d3f3" Offset="0"/>
                    <GradientStop Color="#FF4385BE" Offset="1"/>
                </GradientStopCollection>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>


        <LinearGradientBrush x:Key="BorderBrush" StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FFAFDDF6" Offset="0"/>
                    <GradientStop Color="#FF2969AA" Offset="1"/>
                </GradientStopCollection>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>


        <LinearGradientBrush x:Key="PressedBorderBrush" StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FF75aac7" Offset="0"/>
                    <GradientStop Color="#FF143c65" Offset="1"/>
                </GradientStopCollection>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>


        <Style x:Key="GridViewColumnHeaderGripper" TargetType="Thumb">
            <Setter Property="Width" Value="20"/>
            <Setter Property="Background" Value="#2e566b"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Border Padding="{TemplateBinding Padding}" Background="Transparent">
                            <Rectangle HorizontalAlignment="Center" Width="1" Fill="{TemplateBinding Background}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>


        <Style x:Key="{x:Type GridViewColumnHeader}" TargetType="GridViewColumnHeader">
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Foreground" Value="#FFFFFF" />
            <Setter Property="FontWeight" Value="DemiBold"/>


            <Setter Property="MinWidth" Value="40"/>
            <Setter Property="Height" Value="21"/>


            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="GridViewColumnHeader">
                        <Grid>
                            <Border Name="HeaderBorder" Padding="{TemplateBinding Padding}" BorderThickness="0,1,0,1" BorderBrush="{StaticResource BorderBrush}" Background="{StaticResource BackgroundBrush}">
                                <ContentPresenter Name="HeaderContent" Margin="0,0,0,1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </Border>
                            <Thumb x:Name="PART_HeaderGripper" HorizontalAlignment="Right" Margin="0,0,-9,0" Style="{StaticResource GridViewColumnHeaderGripper}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter TargetName="HeaderBorder" Property="Background" Value="{StaticResource HighlightBackgroundBrush}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter TargetName="HeaderBorder" Property="Background" Value="{StaticResource PressedBorderBrush}"/>
                                <Setter TargetName="HeaderContent" Property="Margin" Value="1,1,0,0"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="Role" Value="Floating">
                    <Setter Property="Opacity" Value="0.7"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="GridViewColumnHeader">
                                <Canvas Name="PART_FloatingHeaderCanvas">
                                    <Rectangle Fill="#60000000" Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}"/>
                                </Canvas>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
                <Trigger Property="Role" Value="Padding">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="GridViewColumnHeader">
                                <Border Name="HeaderBorder" BorderThickness="0,1,0,1" BorderBrush="{StaticResource BorderBrush}" Background="{StaticResource BackgroundBrush}"/>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>


        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalAlignment" Value="Left" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="Height" Value="18" />
            <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
        </Style>


        <Style x:Key="BorderedItem" TargetType="ListViewItem">
            <Setter Property="BorderBrush" Value="Red" />
            <Setter Property="BorderThickness" Value="2" />
        </Style>
        
        <!--ListView Styling End-->
    </Window.Resources>
    <Grid>
        <ListView Name="LstSalesData" Grid.Row="4" Grid.ColumnSpan="3" 
                  ScrollViewer.VerticalScrollBarVisibility="Auto" 
                  Height="300" 
                  Width="580"
                  ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                  SelectionMode="Multiple"
                  Margin="0,6,6,0"
                  VerticalAlignment="Top"
                  GridViewColumnHeader.Click="LstSalesData_Click">
            
            <ListView.Resources>
                <local:BooleanConverter x:Key="boolConverter"/>
            </ListView.Resources>
            
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Order Numner" DisplayMemberBinding="{Binding OrderNumber}" Width="100"/>
                    <GridViewColumn Header="Order Date" DisplayMemberBinding="{Binding OrderDate,StringFormat=MMM dd yyyy}" Width="100"/>
                    <GridViewColumn Header="Customer Name" DisplayMemberBinding="{Binding CustomerName}" Width="100"/>
                    <GridViewColumn Header="Address" DisplayMemberBinding="{Binding Address}" Width="190"/>
                    <GridViewColumn Header="Warranty" DisplayMemberBinding="{Binding Warranty,Converter={StaticResource boolConverter}}" Width="100"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>


********************************************************************************

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;


namespace ListViewTutorial
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {


        List<SalesData> lstSalesData = new List<SalesData>();


        /// <summary>
        /// Initializes a new instance of the <see cref="MainWindow" /> class.
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();
        }


        /// <summary>
        /// Handles the Loaded event of the Window control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs" /> instance containing the event data.</param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            LstSalesData.ItemsSource = GetSalesData();
        }


        /// <summary>
        /// Gets the sales data.
        /// </summary>
        /// <returns></returns>
        private List<SalesData> GetSalesData()
        {
            try
            {
                lstSalesData.Clear();


                Random randNum = new Random();


                String[] states={"Delhi","UP","MP","Ap","Panjap"};
                String[] names = { "Kaushik","Amit","Geeta","Naveen","Priyank","Rahul","Sumit","Pushp","Rohit","Ravi","Anand","Suresh","Rakesh","Ajay","Prabhat"};
                Boolean[] boolVals = { false, true, false, true, false, true, true, false };


                SalesData[] salesdata = new SalesData[10];


                for (int index = 0; index < salesdata.Length; index++)
                {
                    salesdata[index] = new SalesData();
                    salesdata[index].Address = String.Format("House Number  {0}, {1} ", randNum.Next(1, 1000), states[randNum.Next(0, states.Length-1)].ToString());
                    salesdata[index].CustomerName = names[randNum.Next(0, 14)].ToString();
                    salesdata[index].OrderDate = DateTime.Now.AddDays(randNum.Next(1,30));
                    salesdata[index].OrderNumber = randNum.Next(1, 1000);
                    salesdata[index].Warranty =boolVals[randNum.Next(0,boolVals.Length-1)];
                    lstSalesData.Add(salesdata[index]);
                }
            }
            catch (Exception)
            { 
                throw;
            }
            return lstSalesData;
        }


        /// <summary>
        /// Handles the Click event of the LstSalesData control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs" /> instance containing the event data.</param>
        private void LstSalesData_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                ListViewSort sort = new ListViewSort(LstSalesData.ItemsSource, e, this.Resources);
            sort.SortListView();
            }
            catch (Exception)
            {
                throw;
            }
        }
    }


    internal class SalesData
    {
        public SalesData()
        { 
        
        }


        public int OrderNumber { get; set; }
        public DateTime OrderDate { get; set; }
        public String CustomerName { get; set; }
        public String Address { get; set; }
        public Boolean Warranty { get; set; }
    }


    /// <summary>
    /// This class is used for boolean conversion in ListView
    /// </summary>
    internal class BooleanConverter : IValueConverter
    {
        /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value produced by the binding source.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        /// <Developer>Kaushik Kumar Mistry</Developer>
        /// <DateCreated>31 July 2012</DateCreated>
        /// <ModifiedBy>...</ModifiedBy>
        /// <ModifiedDate>...</ModifiedDate>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            String returnValue = String.Empty;
            if ((Boolean)value == true)
            {
                returnValue = "Y";
                return returnValue;
            }
            else
            {
                returnValue = "N";
                return returnValue;
            }
        }


        /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value that is produced by the binding target.</param>
        /// <param name="targetType">The type to convert to.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        /// <Developer>Kaushik Kumar Mistry</Developer>
        /// <DateCreated>31 July 2012</DateCreated>
        /// <ModifiedBy>...</ModifiedBy>
        /// <ModifiedDate>...</ModifiedDate>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Boolean returnValue = false;
            if ((String)value == "Y")
            {
                returnValue = true;
                return returnValue;
            }
            else
            {
                returnValue = false;
                return returnValue;
            }
        }
    }

    /// <summary>
    /// This class is used to sort ListView
    /// </summary>
    internal sealed class ListViewSort
    {
        private static GridViewColumnHeader lastHeaderClicked = null;
        private static ListSortDirection lastDirection = ListSortDirection.Ascending;
        private readonly IEnumerable listViewItemsSource = null;
        private readonly RoutedEventArgs routedEventArgs = null;
        private readonly ResourceDictionary resources = null;


        /// <summary>
        /// This method is used to sort ListView
        /// </summary>
        /// <param name="listViewItemsSource"></param>
        /// <param name="routedEventArgs"></param>
        /// <param name="resources"></param>
        /// <Developer>Kaushik Kumar Mistry</Developer>
        /// <DateCreated>31 July 2012</DateCreated>
        /// <ModifiedBy>...</ModifiedBy>
        /// <ModifiedDate>...</ModifiedDate>
        public ListViewSort(IEnumerable listViewItemsSource, RoutedEventArgs routedEventArgs, ResourceDictionary resources)
        {
            this.listViewItemsSource = listViewItemsSource;
            this.routedEventArgs = routedEventArgs;
            this.resources = resources;
        }


        /// <summary>
        /// Sorts the list view.
        /// </summary>
        /// <Developer>Kaushik Kumar Mistry</Developer>
        /// <DateCreated>31 July 2012</DateCreated>
        /// <ModifiedBy>...</ModifiedBy>
        /// <ModifiedDate>...</ModifiedDate>
        public void SortListView()
        {
            GridViewColumnHeader headerClicked = routedEventArgs.OriginalSource as GridViewColumnHeader;
            ListSortDirection direction;


            if (headerClicked != null)
            {
                if (headerClicked.Role != GridViewColumnHeaderRole.Padding)
                {
                    if (headerClicked != lastHeaderClicked)
                    {
                        direction = ListSortDirection.Ascending;
                    }
                    else
                    {
                        if (lastDirection == ListSortDirection.Ascending)
                        {
                            direction = ListSortDirection.Descending;
                        }
                        else
                        {
                            direction = ListSortDirection.Ascending;
                        }
                    }


                    String header = ((Binding)(headerClicked.Column.DisplayMemberBinding)).Path.Path;


                    Sort(header, direction);


                    if (direction == ListSortDirection.Ascending)
                    {
                        headerClicked.Column.HeaderTemplate = resources["Ascending"] as DataTemplate;
                    }
                    else
                    {
                        headerClicked.Column.HeaderTemplate = resources["Descending"] as DataTemplate;
                    }


                    // Remove arrow from previously sorted header
                    if (lastHeaderClicked != null && lastHeaderClicked != headerClicked)
                    {
                        lastHeaderClicked.Column.HeaderTemplate = null;
                    }


                    lastHeaderClicked = headerClicked;
                    lastDirection = direction;
                }
            }
        }


        /// <summary>
        /// Sorts the specified sort by.
        /// </summary>
        /// <param name="sortBy">The sort by ascending or descending.</param>
        /// <param name="direction">The direction.</param>
        /// <Developer>Kaushik Kumar Mistry</Developer>
        /// <DateCreated>11 July 2012</DateCreated>
        /// <ModifiedBy>...</ModifiedBy>
        /// <ModifiedDate>...</ModifiedDate>
        private void Sort(String sortBy, ListSortDirection direction)
        {
            if (listViewItemsSource != null)
            {
                ICollectionView dataView = CollectionViewSource.GetDefaultView(listViewItemsSource);
                dataView.SortDescriptions.Clear();
                SortDescription sd = new SortDescription(sortBy, direction);
                dataView.SortDescriptions.Add(sd);
                dataView.Refresh();
            }
        }
    }
}

Post a Comment