Group by first letter

4 posts, 0 answers
  1. Inger Marie
    Inger Marie avatar
    86 posts
    Member since:
    Nov 2010

    Posted 19 Mar 2015 Link to this post

    Hi,
    I have a bunch of different RadGridViews, and in each RadGridView there are columns containing names. I want these columns to be grouped by first letter - however I want this:

    * '\0' and String.Empty and null must be grouped together and showed as String.Empty (or null, the user cannot see the difference).
    * Upper case and lower case (such as 'g' and 'G') must be grouped together and showed by the upper case variant.
    * Leading spaces, such as in "     Telerik" should be ignored (so "       Telerik" and "Tony" should both be grouped under "T").

    Is there any way to do this, without creating a separate FirstLetterInName-property on all my ViewModels that has the Name-property (which is a lot)?

    I tried using the GroupHeaderTemplate, but that gets applied after the grouping and only affects the name of the group, not how the grouping is calculated:

     <telerik:GridViewDataColumn x:Name="_contactNameColumn" Width="SizeToHeader"
                                    Header="Name"
                                    DataMemberBinding="{Binding ContactName}"
                                    GroupMemberPath="ContactName[0]"
                                    GroupHeaderTemplate="{StaticResource NameGroupTemplate}"/>
  2. Dimitrina
    Admin
    Dimitrina avatar
    3769 posts

    Posted 21 Mar 2015 Link to this post

    Hello Inger,

    In order to define your own way of grouping, you can apply a generic GroupDescriptor. Please refer to our online documentation on Using generic GroupDescriptor for more details.

    Regards,
    Dimitrina
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. Inger Marie
    Inger Marie avatar
    86 posts
    Member since:
    Nov 2010

    Posted 27 Mar 2015 in reply to Dimitrina Link to this post

    I am sorry, but I cant find a way to do this. I wanted to attach a sample project, but that is not allowed. So I paste in the code instead.

    In this project, I want to group Name and Industry Name on the trimmed values first letter. I want to have " " and String.Empty and null to end up in the same group.

    I want Selected, Industry Code, Country and Description to be grouped traditionally.

    I do not understand how I can do this by using a generic GroupDescriptor because I do not know how I can make the RadGridView use this group selector on some columns but not others.

    Can you help me please?


    public partial class MainWindow : Window, INotifyPropertyChanged
     {
         public MainWindow()
         {
             InitializeComponent();
             DataContext = this;
     
     
             Companies.Add(new Company(" ", "2345", "Beverages", "PL", GetDescription()));
             Companies.Add(new Company(String.Empty, null, null, "DE", GetDescription()));
             Companies.Add(new Company("Absolute", null, null, "DE", GetDescription()));
             Companies.Add(new Company(" Alcohol", "2345", "Beverages", "DK", GetDescription()));
             Companies.Add(new Company("Bikes", "4354", "Transportation", "DE", GetDescription()));
             Companies.Add(new Company(null, "4354", "Transportation", "PL", GetDescription()));
             Companies.Add(new Company("Whiskey", "2345", "Beverages", "UK", GetDescription()));
         }
     
         private string GetDescription()
         {
             List<string> words = new List<string>();
             for (int i = 0; i < RandomSampleData.GetInt(new RandomBoundary(2, 6)); i++)
             {
                 words.Add(RandomSampleData.GetString());
             }
             return String.Join(" ", words);
         }
     
     
         #region INotifyPropertyChanged Members
     
         /// <summary>
         /// Raises this object's PropertyChanged event.
         /// </summary>
         /// <param name="propertyName">The property that has a new value.</param>
         protected void RaisePropertyChanged(string propertyName)
         {
             if (PropertyChanged != null)
             {
                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
             }
         }
     
         public event PropertyChangedEventHandler PropertyChanged;
     
         private void CurrentProjectSuppliers_OnFilterOperatorsLoading(object sender, FilterOperatorsLoadingEventArgs e)
         {
             e.AvailableOperators.Remove(FilterOperator.IsContainedIn);
             e.AvailableOperators.Remove(FilterOperator.IsNotContainedIn);
     
             if (e.Column.Equals(_nameColumn)
                 || e.Column.Equals(_iNameColumn)
                 || e.Column.Equals(_descriptionColumn))
             {
                 e.AvailableOperators.Remove(FilterOperator.IsEmpty);
                 e.AvailableOperators.Remove(FilterOperator.IsGreaterThan);
                 e.AvailableOperators.Remove(FilterOperator.IsGreaterThanOrEqualTo);
                 e.AvailableOperators.Remove(FilterOperator.IsLessThan);
                 e.AvailableOperators.Remove(FilterOperator.IsLessThanOrEqualTo);
                 e.AvailableOperators.Remove(FilterOperator.IsNotEmpty);
                 return;
             }
             if (e.Column.Equals(_iCodeColumn))
             {
                 e.AvailableOperators.Remove(FilterOperator.DoesNotContain);
                 e.AvailableOperators.Remove(FilterOperator.Contains);
                 e.AvailableOperators.Remove(FilterOperator.EndsWith);
                 e.AvailableOperators.Remove(FilterOperator.IsEmpty);
                 e.AvailableOperators.Remove(FilterOperator.IsGreaterThanOrEqualTo);
                 e.AvailableOperators.Remove(FilterOperator.IsLessThanOrEqualTo);
                 e.AvailableOperators.Remove(FilterOperator.IsNotEmpty);
                 e.AvailableOperators.Remove(FilterOperator.IsNotNull);
                 e.AvailableOperators.Remove(FilterOperator.IsNull);
                 return;
             }
     
         }
     
         private void CurrentProjectSuppliers_OnFieldFilterEditorCreated(object sender, EditorCreatedEventArgs e)
         {
     
             StringFilterEditor stringFilterEditor = e.Editor as StringFilterEditor;
             if (stringFilterEditor != null)
             {
                 stringFilterEditor.MatchCaseVisibility = Visibility.Hidden;
                 stringFilterEditor.IsCaseSensitive = false;
             }
     
         }
     
         #endregion
     
         private readonly ObservableCollection<Company> _companies = new ObservableCollection<Company>();
     
         public ObservableCollection<Company> Companies
         {
             get { return _companies; }
         }
     }

    <Window x:Class="Sandbox.MainWindow"
            xmlns:Sandbox="clr-namespace:Sandbox"
            Title="MainWindow">
        
    <Window.Resources>
            <SolidColorBrush x:Key="RowBrush" Color="White" />
            <SolidColorBrush x:Key="SelectedRowColor" Color="#FF3399FF" />
            <SolidColorBrush x:Key="MouseOverRowColor" Color="#FFA5A5A5" />
            <SolidColorBrush x:Key="AlternateRowBrush" Color="#E9F0FF" />
             
        <Style TargetType="{x:Type telerik:GridViewRow}" x:Key="RadGridViewRowStyle">
                <Setter Property="Background" Value="{StaticResource RowBrush}" />
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background" Value="{StaticResource SelectedRowColor}" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{StaticResource MouseOverRowColor}" />
                    </Trigger>
                </Style.Triggers>
            </Style>
     
            <Style TargetType="{x:Type telerik:GridViewRow}" x:Key="RadGridViewAlternateRowStyle">
                <Setter Property="Background" Value="{StaticResource AlternateRowBrush}" />
                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background" Value="{StaticResource SelectedRowColor}" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{StaticResource MouseOverRowColor}" />
                    </Trigger>
                </Style.Triggers>
            </Style>
         
         
            <Style TargetType="{x:Type telerik:RadGridView}" x:Key="RadGridViewStyle" >
                <Setter Property="RowIndicatorVisibility" Value="Collapsed" />
                <Setter Property="AlternationCount"
                    Value="2" />
     
                <Setter Property="AutoGenerateColumns"
                    Value="False" />
                <Setter Property="IsFilteringAllowed"               
                    Value="False" />
                <Setter Property="CanUserInsertRows"
                    Value="False" />
                <Setter Property="CanUserDeleteRows"
                    Value="False" />
                <Setter Property="RowStyle" Value="{StaticResource RadGridViewRowStyle}" />
                <Setter Property="AlternateRowStyle" Value="{StaticResource RadGridViewAlternateRowStyle}" />
            </Style>
     
            <Sandbox:Bool2Visibility TrueResult="Visible" FalseResult="Collapsed" x:Key="False2Collapsed"/>
            <Sandbox:Bool2Visibility TrueResult="Collapsed" FalseResult="Visible" x:Key="True2Collapsed"/>
     
        </Window.Resources>
         
        <telerik:RadGridView x:Name="_currentProjectSuppliers"
            FrozenColumnsSplitterVisibility="Collapsed"
                             FilteringMode="Popup"
                             IsFilteringAllowed="True"
                            Style="{StaticResource RadGridViewStyle}"
                            ItemsSource="{Binding Companies}"
                            IsSynchronizedWithCurrentItem="False"
                             HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
                             VerticalAlignment="Stretch" VerticalContentAlignment="Stretch"
                                VisibleRowsHeight="25"
                                CanUserSortColumns="True"
                             CanUserSortGroups="True"
                             FieldFilterEditorCreated ="CurrentProjectSuppliers_OnFieldFilterEditorCreated"
                             FilterOperatorsLoading="CurrentProjectSuppliers_OnFilterOperatorsLoading">
            <telerik:RadGridView.Resources>
                <ResourceDictionary>
                    <!--<LinearGradientBrush x:Key="GridView_FilterIconBackground_Filtered" EndPoint="0,0.5" StartPoint="1,0.5">
                        <GradientStop Color="#FFFF7300" Offset="0"/>
                        <GradientStop Color="#FFFFF400" Offset="0.8"/>
                    </LinearGradientBrush>-->
     
                    <Style TargetType="telerik:GridViewCell">
                        <Setter Property="Padding" Value="2"/>
                        <Setter Property="VerticalContentAlignment" Value="Center"/>
                        <Setter Property="HorizontalContentAlignment" Value="Right" />
                    </Style>
     
                    <Style TargetType="telerik:GridViewCell" x:Key="CenteredCell">
                        <Setter Property="HorizontalContentAlignment" Value="Center" />
                    </Style>
     
                    <Style TargetType="telerik:GridViewCell" x:Key="LefteredCell">
                        <Setter Property="HorizontalContentAlignment" Value="Left" />
                    </Style>
                </ResourceDictionary>
            </telerik:RadGridView.Resources>
            <telerik:RadGridView.SortDescriptors>
                <telerik:SortDescriptor Member="NaceCode.NaceCode" SortDirection="Ascending" />
            </telerik:RadGridView.SortDescriptors>
            <telerik:RadGridView.Columns>
     
     
                <telerik:GridViewDataColumn x:Name="_isSelectedColumn"
                                          IsSortable="True"
                                        IsFilterable="True"
                                        ShowFieldFilters="False"
                                        FilterMemberPath="IsSelected"
                                        SortMemberPath="IsSelected"
                                        Width="SizeToHeader"
                                        CellStyle="{StaticResource CenteredCell}"
                                        DataMemberBinding="{Binding Path=(Sandbox:Company.IsSelected)}" IsReadOnly="True"
                                        GroupMemberPath="IsSelected">
                    <telerik:GridViewDataColumn.Header>
                        <TextBlock Text="Selected"  />
                    </telerik:GridViewDataColumn.Header>
                    <telerik:GridViewDataColumn.CellTemplate>
                        <DataTemplate DataType="{x:Type Sandbox:Company}">
                            <!--<Image Height="16" Width="16"
                                VerticalAlignment="Center" HorizontalAlignment="Center"
                               Source="{StaticResource SingleCheckImageSmall}"
                               Visibility="{Binding IsSelected, Converter={StaticResource False2Collapsed}}" />-->
                            <TextBlock Height="16" Width="16"
                                VerticalAlignment="Center" HorizontalAlignment="Center"
                              Text="Selected"
                               Visibility="{Binding IsSelected, Converter={StaticResource False2Collapsed}}" />
                        </DataTemplate>
                    </telerik:GridViewDataColumn.CellTemplate>
                </telerik:GridViewDataColumn>
     
                 
     
                <telerik:GridViewDataColumn x:Name="_nameColumn"
                                        Width="260"
                                        IsFilterable="True"
                                        IsSortable="True"
                                        ShowDistinctFilters="False"
                                        FilterMemberPath="Name"
                                        CellStyle="{StaticResource LefteredCell}"
                                        DataMemberBinding="{Binding Path=(Sandbox:Company.Name)}" IsReadOnly="True"
                                             SortMemberPath="Name"
                                            GroupMemberPath="Name"
                                        IsGroupable="True">
                    <!--GroupMemberPath="Name[0]"-->
                    <telerik:GridViewDataColumn.Header>
                        <TextBlock Text="Name"
                                               ToolTip="Name" />
                    </telerik:GridViewDataColumn.Header>
                </telerik:GridViewDataColumn>
     
                <!--SortMemberPath="NaceCode.NaceCode"-->
                <telerik:GridViewDataColumn x:Name="_iCodeColumn"
                                       IsSortable="True"
                                        IsFilterable="True"
                                        ShowDistinctFilters="False"
                                        ShowFieldFilters="True"
                                        FilterMemberPath="IndustryCode"
                                        GroupMemberPath="IndustryCode"
                                            SortMemberPath="IndustryCode"
                                        Width="SizeToHeader"
                                        CellStyle="{StaticResource LefteredCell}"
                                        DataMemberBinding="{Binding Path=(Sandbox:Company.IndustryCode)}" IsReadOnly="True"
                                        IsGroupable="True">
                    <telerik:GridViewDataColumn.Header>
                        <TextBlock Text="Industry Code"
                                               ToolTip="Industry Code" />
                    </telerik:GridViewDataColumn.Header>
                </telerik:GridViewDataColumn>
     
     
                <!--GroupMemberPath="NaceCode.IndustryName[0]"-->
                <telerik:GridViewDataColumn x:Name="_iNameColumn"
                                       IsSortable="True"
                                        IsFilterable="True"
                                       ShowDistinctFilters="False"
                                         FilterMemberPath="IndustryName"
                                             SortMemberPath="IndustryName"
                                            GroupMemberPath="IndustryName"
                                        Width="220"
                                        CellStyle="{StaticResource LefteredCell}"
                                        MaxWidth="320"
                                        DataMemberBinding="{Binding Path=(Sandbox:Company.IndustryName)}" IsReadOnly="True">
                    <telerik:GridViewDataColumn.Header>
                        <TextBlock Text="Industry Name"
                                               ToolTip="Industry Name" />
                    </telerik:GridViewDataColumn.Header>
                </telerik:GridViewDataColumn>
     
     
                <telerik:GridViewDataColumn x:Name="_countryColumn"
                                       IsSortable="True"
                                        IsFilterable="True"
                                        ShowFieldFilters="False"
                                        FilterMemberPath="CountryISOName"
                                             SortMemberPath="CountryISOName"
                                        Width="SizeToHeader"
                                        CellStyle="{StaticResource LefteredCell}"
                                        DataMemberBinding="{Binding Path=(Sandbox:Company.CountryISOName)}" IsReadOnly="True"
                                        GroupMemberPath="Country.ShortNameISO">
                    <telerik:GridViewDataColumn.Header>
                        <TextBlock Text="Country"
                                               ToolTip="Country" />
                    </telerik:GridViewDataColumn.Header>
                </telerik:GridViewDataColumn>
     
     
                <!--GroupMemberPath="Master.Name[0]"-->
                <telerik:GridViewDataColumn x:Name="_descriptionColumn"
                                       IsSortable="True"
                                        ShowDistinctFilters="False"
                                        IsFilterable="True"
                                        FilterMemberPath="Description"
                                             SortMemberPath="Description"
                                        Width="SizeToHeader"
                                        CellStyle="{StaticResource LefteredCell}"
                                        DataMemberBinding="{Binding Path=(Sandbox:Company.Description)}" IsReadOnly="True">
                    <telerik:GridViewDataColumn.Header>
                        <TextBlock Text="Description"
                                               ToolTip="Description" />
                    </telerik:GridViewDataColumn.Header>
                </telerik:GridViewDataColumn>
     
            </telerik:RadGridView.Columns>
        </telerik:RadGridView>
    </Window>

    public class Bool2Visibility : IValueConverter
       {
           public Visibility TrueResult { get; set; }
           public Visibility FalseResult { get; set; }
     
           public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
           {
               if (value == null) return FalseResult;
               return ((value is bool?) ? (bool?)value == true : (bool)value) ? TrueResult : FalseResult;
           }
     
           public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
           {
               throw new NotImplementedException();
           }
     
     
           Visibility Method(object value, Type targetType, object parameter, CultureInfo culture)
           {
               return ((value is bool?) ? (bool?)value == true : (bool)value) ? TrueResult : FalseResult;
           }
       }

    public class Company : ViewModelBase
      {
     
          public Company(string name, string iCode, string iName, string country, string description)
          {
              Name = name;
              IndustryCode = iCode;
              IndustryName = iName;
              CountryISOName = country;
              Description = description;
          }
          private bool _isSelected;
          private string _name;
          private string _industryCode;
          private string _industryName;
          private string _countryISOName;
          private string _description;
     
          public bool IsSelected
          {
              get { return _isSelected; }
              set { _isSelected = value; RaisePropertyChanged(() => IsSelected);}
          }
     
          public string Name
          {
              get { return _name; }
              set { _name = value; RaisePropertyChanged(() => Name); }
          }
     
          public string IndustryCode
          {
              get { return _industryCode; }
              set { _industryCode = value; RaisePropertyChanged(() => IndustryCode); }
          }
     
          public string IndustryName
          {
              get { return _industryName; }
              set { _industryName = value; RaisePropertyChanged(() => IndustryName); }
          }
     
          public string CountryISOName
          {
              get { return _countryISOName; }
              set { _countryISOName = value; RaisePropertyChanged(() => CountryISOName); }
          }
     
          public string Description
          {
              get { return _description; }
              set { _description = value; RaisePropertyChanged(() => Description); }
          }
      }

    public class RandomBoundary
      {
          public RandomBoundary(int? minValue, int? maxValue)
          {
              MinValue = minValue;
              MaxValue = maxValue;
          }
          public int? MinValue { get; private set; }
          public int? MaxValue { get; private set; }
      }
     
      public static class RandomSampleData
      {
          private static readonly Random Random = new Random();
     
          public static int GetInt(RandomBoundary boundary = null)
          {
              if (boundary == null || (boundary.MinValue == null && boundary.MaxValue == null))
              {
                  return Random.Next();
              }
              if (boundary.MinValue == null)
              {
                  Debug.Assert(boundary.MaxValue != null);
                  return Random.Next(boundary.MaxValue.Value);
              }
              return Random.Next(boundary.MinValue.Value, boundary.MinValue.Value);
          }
     
          public static bool GetBool()
          {
     
              return Random.Next() % 2 == 0;
          }
     
          public static bool? GetNullableBool()
          {
     
              int x = Random.Next() % 3;
              switch (x)
              {
                  case 2:
                      return true;
                  case 1:
                      return false;
                  default:
                      return new bool?();
              }
          }
     
     
          public static string GetString(string prefix = null, string postfix = null)
          {
              return String.Format("{0}{1}{2}", prefix ?? String.Empty, Random.Next(), postfix ?? String.Empty);
          }
     
     
          public static decimal GetDecimal(RandomBoundary boundary)
          {
              decimal part = (decimal)Random.NextDouble();
              return GetInt(boundary) + part;
          }
     
     
     
          public static decimal? GetNullableDecimal(RandomBoundary boundary)
          {
     
              if (GetBool())
                  return GetDecimal(boundary);
              return new decimal?();
          }
     
          public static T GetEnum<T>(T sample)
          {
     
              Array array = Enum.GetValues(typeof(T));
              int index = Random.Next() % array.Length;
              return (T)((IList)array)[index];
          }
     
          public static T GetEnum<T>(T[] allowableValues)
          {
     
              int index = Random.Next() % allowableValues.Length;
              return allowableValues[index];
          }
     
          public static DateTime GetDate(bool inPast = true, int maxDays = 30)
          {
     
              int days = Random.Next(maxDays);
              return inPast ? DateTime.Now.AddDays(-days) : DateTime.Now.AddDays(days);
          }
     
          public static DateTime? GetNullableDate(bool inPast = true, int maxDays = 30)
          {
     
              if (GetBool())
              {
                  return GetDate(inPast, maxDays);
              }
              return new DateTime?();
          }
     
      }

    Thanks,
    Best regards
    Inger Marie
  4. Dimitrina
    Admin
    Dimitrina avatar
    3769 posts

    Posted 30 Mar 2015 Link to this post

    Hi Inger,

    You can subscribe for the Grouping event of RadGridView and replace the added ColumnGroupDescriptor with a new generic one where you have specified a proper GroupExpression and GroupSortingExpresstion.

    Such an example is available in the following forum thread. Would you please try it? In case it does not help, you can open a new support ticket and attach your sample project there.


    Regards,
    Dimitrina
    Telerik
     

    See What's Next in App Development. Register for TelerikNEXT.

     
Back to Top