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 :
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.
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 { get; set; } |
private string ns { get; set; } |
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 { get; set; } |
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.