This is a migrated thread and some comments may be shown as answers.

Dynamic Column & Custom Sorting

2 Answers 197 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Ludovic Alcala
Top achievements
Rank 1
Ludovic Alcala asked on 03 Mar 2010, 04:43 PM
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 Answers, 1 is accepted

Sort by
0
Vlad
Telerik team
answered on 05 Mar 2010, 08:13 AM
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.
0
Ludovic Alcala
Top achievements
Rank 1
answered on 05 Mar 2010, 08:39 AM
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.
Tags
GridView
Asked by
Ludovic Alcala
Top achievements
Rank 1
Answers by
Vlad
Telerik team
Ludovic Alcala
Top achievements
Rank 1
Share this question
or