Dynamic Column & Custom Sorting

3 posts, 0 answers
  1. Ludovic Alcala
    Ludovic Alcala avatar
    24 posts
    Member since:
    Jan 2010

    Posted 03 Mar 2010 Link to this post

    Hello,
    i have a project where we have this kind of object :

    - ListingProduct (DisplayName, List<property>) which properties is  a Property {string name, string value}.

    And i need to offer to my users the choice of shown column (who correspond to properties) by a context menu on header fields.

    Here the code :
    using System; 
    using System.Net; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Documents; 
    using System.Windows.Ink; 
    using System.Windows.Input; 
    using System.Windows.Media; 
    using System.Windows.Media.Animation; 
    using System.Windows.Shapes; 
    using System.ComponentModel; 
    using Telerik.Windows.Controls; 
    using Telerik.Windows.Controls.GridView; 
    using Telerik.Windows; 
    using System.Windows.Data; 
    using System.Collections.Generic; 
    using System.Linq; 
    using CatalogManager.WCFCatalogManager; 
    using System.Collections.ObjectModel; 
    using Telerik.Windows.Data; 
    using System.Collections; 
    using System.Diagnostics; 
    namespace CatalogManager.Views.CatalogV.Renderer 
        public class HeaderColumnChooser 
        { 
     
            private RadGridView grid = null
            public HeaderColumnChooser(RadGridView grid) 
            { 
                this.grid = grid; 
            } 
     
            public static readonly DependencyProperty IsEnabledProperty 
                = DependencyProperty.RegisterAttached("IsEnabled"typeof(bool), typeof(HeaderColumnChooser), 
                    new System.Windows.PropertyMetadata(new PropertyChangedCallback(OnIsEnabledPropertyChanged))); 
     
            public static void SetIsEnabled(DependencyObject dependencyObject, bool enabled) 
            { 
                dependencyObject.SetValue(IsEnabledProperty, enabled); 
            } 
     
            public static bool GetIsEnabled(DependencyObject dependencyObject) 
            { 
                return (bool)dependencyObject.GetValue(IsEnabledProperty); 
            } 
     
            private static void OnIsEnabledPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
            { 
                RadGridView grid = dependencyObject as RadGridView; 
                if (grid != null
                { 
                    if ((bool)e.NewValue) 
                    { 
                        // Create new GridViewHeaderMenu and attach RowLoaded event. 
                        HeaderColumnChooser menu = new HeaderColumnChooser(grid); 
                        menu.Attach(); 
     
     
                    } 
                } 
            } 
            private void Attach() 
            { 
                if (grid != null
                { 
                    this.grid.Loaded += new RoutedEventHandler(grid_Loaded); 
                    this.grid.DataLoaded += new EventHandler<EventArgs>(grid_DataLoaded); 
                    this.grid.Sorting += new EventHandler<GridViewSortingEventArgs>(grid_Sorting); 
                    this.grid.Sorted += new EventHandler<GridViewSortedEventArgs>(grid_Sorted); 
                    this.grid.SortDescriptors.Clear(); 
                } 
            } 
     
            
     
     
            void grid_Sorted(object sender, GridViewSortedEventArgs e) 
            { 
                e.Handled = true
            } 
            private SortingState st { getset; } 
            private string ns { getset; } 
            void grid_Sorting(object sender, GridViewSortingEventArgs e) 
            { 
                string action = ""
                if (e.NewSortingState == SortingState.Ascending) 
                    action = "SortAsc"
                else if (e.NewSortingState == SortingState.Descending) 
                    action = "SortDesc"
                else 
                    action = "ClearSort"
                SortGrid(e.Column, action); 
                ns = e.Column.UniqueName; 
                if (e.OldSortingState == SortingState.None) 
                { 
                    e.NewSortingState = SortingState.Ascending; 
                     
                } 
                else if (e.OldSortingState == SortingState.Ascending) 
                { 
                    e.NewSortingState = SortingState.Descending; 
                     
                } 
                else 
                { 
                    e.NewSortingState = SortingState.None; 
                     
                } 
                e.Column.SortingState = e.NewSortingState; 
                e.Cancel = true
     
            } 
     
            void grid_DataLoaded(object sender, EventArgs e) 
            { 
                GridViewHeaderRow headerRow = grid.ChildrenOfType<GridViewHeaderRow>().FirstOrDefault(); 
                if (headerRow != null
                { 
                    InitializeMenus(headerRow); 
                } 
            } 
     
            void grid_Loaded(object sender, RoutedEventArgs e) 
            { 
     
            } 
     
            private void InitializeMenus(GridViewHeaderRow row) 
            { 
                IEnumerable<GridViewHeaderCell> cells = row.Cells.OfType<GridViewHeaderCell>(); 
     
                foreach (GridViewHeaderCell cell in cells) 
                { 
                    // create menu 
                    RadContextMenu contextMenu = new RadContextMenu(); 
                    // set menu Theme 
                    StyleManager.SetTheme(contextMenu, StyleManager.GetTheme(grid)); 
     
                    RadMenuItem item = new RadMenuItem() { Name = "SortAsc", Header = String.Format(@"Trier par ordre croissant par ""{0}""", cell.Column.Header) }; 
                    contextMenu.Items.Add(item); 
     
                    item = new RadMenuItem() { Name = "SortDesc", Header = String.Format(@"Trier par ordre décroissant par ""{0}""", cell.Column.Header) }; 
                    contextMenu.Items.Add(item); 
     
                    item = new RadMenuItem() { Name = "ClearSort", Header = String.Format(@"Effacer le tri de ""{0}""", cell.Column.Header) }; 
                    contextMenu.Items.Add(item); 
     
                    item = new RadMenuItem() { Name = "ChooseColumns", Header = "Choisir les colonnes" }; 
                    contextMenu.Items.Add(item); 
     
     
                    contextMenu.AddHandler(RadMenuItem.ClickEvent, new RoutedEventHandler(OnMenuItemClick)); 
     
                    // attach menu 
                    RadContextMenu.SetContextMenu(cell, contextMenu); 
                } 
            } 
     
            void OnMenuItemClick(object sender, RoutedEventArgs e) 
            { 
                RadContextMenu menu = (RadContextMenu)sender; 
                RadMenuItem clickedItem = ((RadRoutedEventArgs)e).OriginalSource as RadMenuItem; 
                GridViewColumn column = ((GridViewHeaderCell)menu.UIElement).Column; 
     
                if (clickedItem.Parent is RadMenuItem) 
                    return
     
                string header = Convert.ToString(clickedItem.Name); 
                if (header == "ChooseColumns"
                { 
                    ObservableCollection<InfoPropSchema> props; 
                    props = (grid.ParentOfType<CatalogProducts>()).propsSchema; 
                    ChooseProperties chooseProperties = new ChooseProperties(props); 
                    chooseProperties.Closing += new EventHandler<CancelEventArgs>(chooseProperties_Closing); 
                    chooseProperties.Show(); 
                    return
                } 
                SortGrid(column, header); 
            } 
            void SortGrid(GridViewColumn column, string action) 
            { 
                if (grid.Columns.Count > 4)  
                Debug.WriteLine(System.DateTime.Now.ToString() + " " + grid.Columns[4].SortingState + " - SortGridStart"); 
                using (grid.DeferRefresh()) 
                { 
                    InfoPropSchema ips = (grid.ParentOfType<CatalogProducts>()).propsSchema.First(o => o.Name == column.UniqueName); 
                    SortedCollection<ListingCatalogItem> soc = new SortedCollection<ListingCatalogItem>(new sortInfoProp(ips)); 
                    ObservableCollection<ListingCatalogItem> list; 
                    if ((grid.ParentOfType<CatalogProducts>()).MyDefinitionType == DefinitionType.ProductDefinition) 
                    { 
                        list = ((grid.ParentOfType<CatalogProducts>()).MyCollection); 
                    } 
                    else 
                    { 
                        list = ((grid.ParentOfType<CatalogProducts>()).MyCollectionSousCategories); 
                    } 
                    switch (action) 
                    { 
                        case "SortAsc"
                            list.ToList().ForEach(o => soc.Add(o)); 
                            list.Clear(); 
                            soc.ToList().ForEach(o => list.Add(o)); 
                            (grid.ItemsSource as QueryableCollectionView).Refresh(); 
                            soc.Clear(); 
                            soc = null
                            break
                        case "SortDesc"
                            list.ToList().ForEach(o => soc.Add(o)); 
                            list.Clear(); 
                            soc.Reverse().ToList().ForEach(o => list.Add(o)); 
                            (grid.ItemsSource as QueryableCollectionView).Refresh(); 
                            soc.Clear(); 
                            soc = null
                            break
                        case "ClearSort"
     
                            break
                    } 
                } 
            } 
            void chooseProperties_Closing(object sender, CancelEventArgs e) 
            { 
                Reload(true); 
            } 
     
            public void Reload(bool rebind) 
            { 
                GridViewColumnCollection gvcc = new GridViewColumnCollection(); 
                grid.SortDescriptors.Clear(); 
                grid.Columns.Clear(); 
                grid.Columns.Add(new GridViewToggleRowDetailsColumn() 
                { 
                    Header = "QuickEdit" 
                }); 
                (grid.ParentOfType<CatalogProducts>()).propsSchema.Where(o => o.IsShown).ToList().ForEach( 
                      delegate(InfoPropSchema a) 
                      { 
                          if (!gvcc.Any<GridViewColumn>(o => o != null && o.UniqueName == a.Name)) 
                          { 
                              Binding myBind = new Binding("ListProperties"
                              { 
                                  Converter = new ListPropriete(a), 
                                  ConverterParameter = a.Name 
                              }; 
     
                              gvcc.Add( 
                                  new GridViewDataColumn() 
                                  { 
                                      Header = a.DisplayName, 
                                      DataMemberBinding = myBind, 
                                      UniqueName = a.Name, 
                                      IsReorderable = false
                                      IsFilterable = false
                                      IsSortable=true
                                      SortMemberPath = a.Name, 
                                      DataType = typeof(String) 
                                  } 
                              ); 
                          } 
                      }); 
     
     
                gvcc.ToList<GridViewColumn>().ForEach(o => grid.Columns.Add(o)); 
                if (rebind) 
                    grid.Rebind(); 
            } 
     
        } 
        public class sortInfoProp : IComparer<ListingCatalogItem> 
        { 
            private InfoPropSchema _propertyNameToSort; 
            public sortInfoProp(InfoPropSchema propertyNameToSort) 
            { 
                _propertyNameToSort = propertyNameToSort; 
            } 
            #region IComparer<ListingCatalogItem> Members 
     
            public int Compare(ListingCatalogItem x, ListingCatalogItem y) 
            { 
                ListingInfoProp FromCompare = x.ListProperties.FirstOrDefault(o => o.Name == _propertyNameToSort.Name); 
                ListingInfoProp ToCompare = y.ListProperties.FirstOrDefault(o => o.Name == _propertyNameToSort.Name); 
                if (FromCompare != null && ToCompare == null
                    return 1; 
                else if (FromCompare == null && ToCompare != null
                    return -1; 
                else if (FromCompare == null && ToCompare == null || FromCompare.Value == ToCompare.Value) 
                    return 0; 
                switch (_propertyNameToSort.ItemDataType) 
                { 
                    case ItemDataType.BigInteger: 
                        return long.Parse(FromCompare.Value).CompareTo(long.Parse(ToCompare.Value)); 
                    case ItemDataType.Boolean: 
                        return Boolean.Parse(FromCompare.Value).CompareTo(Boolean.Parse(ToCompare.Value)); 
                    case ItemDataType.Currency: 
                        return Decimal.Parse(FromCompare.Value).CompareTo(Decimal.Parse(ToCompare.Value)); 
                    case ItemDataType.DateTime: 
                        return DateTime.Parse(FromCompare.Value).CompareTo(DateTime.Parse(ToCompare.Value)); 
                    case ItemDataType.Double: 
                        return Double.Parse(FromCompare.Value).CompareTo(Double.Parse(ToCompare.Value)); 
                    case ItemDataType.Float: 
                        return float.Parse(FromCompare.Value).CompareTo(float.Parse(ToCompare.Value)); 
                    case ItemDataType.Integer: 
                        return int.Parse(FromCompare.Value).CompareTo(int.Parse(ToCompare.Value)); 
                    default
                        return FromCompare.Value.CompareTo(ToCompare.Value); 
     
                } 
            } 
            #endregion 
        } 
        public static class InfoPropExtensions 
        { 
            public static object GetTypedValue(this ListingInfoProp b, InfoPropSchema schemaProperty) 
            { 
                if (b == null
                    return ""
                switch (schemaProperty.ItemDataType) 
                { 
                    case ItemDataType.Boolean: 
                        return String.IsNullOrEmpty(b.Value) ? false : Boolean.Parse(b.Value); 
                    case ItemDataType.String: 
                        return b.Value; 
                    default
                        return b.Value; 
                } 
            } 
        } 
     
        internal class ListPropriete : IValueConverter 
        { 
            private InfoPropSchema schemaProperty { getset; } 
            public ListPropriete(InfoPropSchema _schemaProperty) 
            { 
                schemaProperty = _schemaProperty; 
            } 
            #region IValueConverter Members 
     
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
            { 
                if (value is ObservableCollection<ListingInfoProp> && parameter != null && parameter is string
                { 
                    string tmp = (string)parameter; 
                    return (value as ObservableCollection<ListingInfoProp>).FirstOrDefault(o => o.Name == tmp).GetTypedValue(schemaProperty); 
     
                } 
                else 
                { 
                    return value; 
                } 
            } 
     
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
            { 
                return ""
            } 
            #endregion 
        } 
     




    When i sort by context menu, all works fine.
    But i want to use the same hability by clicking on header.
    So,
    i tried to manage that in Sorting Event, but when i set the new Sorting State, it seem to be lost, have you an idea ?

    I don't want to use the custom DataTable you provided (http://blogs.telerik.com/blogs/posts/09-04-23/lightweight_datatable_for_your_silverlight_applications.aspx and http://blogs.telerik.com/blogs/Libraries/Vladimir_Enchev/SilverlightDataTable_Q3_2009_SP2.sflb?download=true is broken),
    because i need to have the possibility to loadrowdetails without loading and have context menu action on each element (like modify and other), and if i haven't the id column, i cannot retrieve the value.

    Thank you.


  2. Vlad
    Admin
    Vlad avatar
    11100 posts

    Posted 05 Mar 2010 Link to this post

    Hi ,

    You can set SortingState similar to this demo:
    http://demos.telerik.com/silverlight/#GridView/Performance/ServerSide

    I've just checked our updated version of the DataTable however the download link works fine:
    http://blogs.telerik.com/Libraries/Vladimir_Enchev/SilverlightDataTable_Q3_2009_SP2.sflb?download=true

    Regards,
    Vlad
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  3. DevCraft banner
  4. Ludovic Alcala
    Ludovic Alcala avatar
    24 posts
    Member since:
    Jan 2010

    Posted 05 Mar 2010 Link to this post

    Hello,
    thank you for your response.

    But i set the sorting state, and i after the return of method "Sorting", it seem be lost.

    Any idea ?

    Thank you.
Back to Top