Inger Marie
Top achievements
Rank 1
Inger Marie
asked on 19 Mar 2015, 08:23 AM
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}"/>
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}"/>
3 Answers, 1 is accepted
0
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
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.
0
Inger Marie
Top achievements
Rank 1
answered on 27 Mar 2015, 08:45 AM
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?
Thanks,
Best regards
Inger Marie
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:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
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
0
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
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.