or
I had to create a custom column generator with additional logic. It uses reflection to retrieve information about required fields and generates columns.
var gridColumn = new Telerik.Windows.Controls.GridViewDataColumn {
Header = attributes[0].Header, IsVisible = attributes[0].IsVisible,
UniqueName = property.Name,
DataMemberBinding = new Binding(string.Format("Item.{0}", property.Name)),
}It works perfectly except grouping and sorting. However I turned on, that user can sort, and the
grid is groupable and sortable.this.InternalGrid.GroupDescriptors.Add(new Telerik.Windows.Controls.GridView.ColumnGroupDescriptor()
{ Column = this.InternalGrid.Columns[1] });
Grouping seems to be working, it adds the correct column to the group panel, however there is only one group
which contains all of the rows. Sorting is working alike, indicator shows the correct sorting option but nothing
happens. What am I missing here?
<telerik:RadDataPager Grid.Row="3" x:Name="radDataPager" Source="{Binding SearchResults}" PageSize="5" DisplayMode="All" IsTotalItemCountFixed="True" /><telerik:RadGridView x:Name="grdSearchResults" Grid.Row="4" ItemsSource="{Binding PagedSource, ElementName=radDataPager}" IsBusy="{Binding IsSearchActive}" IsReadOnly="True" CanUserDeleteRows="False" CanUserInsertRows="False" ShowGroupPanel="False" Width="auto" AutoGenerateColumns="False" ReorderColumnsMode="Interactive" RowIndicatorVisibility="Collapsed" AutoExpandGroups="True" SelectionMode="Extended"> <telerik:RadGridView.GroupDescriptors> <telerik:GroupDescriptor Member="AccountNumber" SortDirection="Ascending" /> <telerik:GroupDescriptor Member="DocumentType" SortDirection="Ascending" /> </telerik:RadGridView.GroupDescriptors> <i:Interaction.Behaviors> <Behaviors:MultiSelectBehavior SelectedItems="{Binding SelectedDocuments}"/> </i:Interaction.Behaviors> <telerik:RadGridView.Columns> <telerik:GridViewDataColumn Header="ID" DataMemberBinding="{Binding EntryId}" /> <telerik:GridViewDataColumn Header="Status" DataMemberBinding="{Binding Status}" /> <telerik:GridViewDataColumn Header="Created" DataMemberBinding="{Binding CreateDate}" /> <telerik:GridViewSelectColumn /> </telerik:RadGridView.Columns> <i:Interaction.Triggers> <i:EventTrigger EventName="RowActivated" > <i:InvokeCommandAction Command="{Binding DisplayViewCommand}" /> </i:EventTrigger> </i:Interaction.Triggers></telerik:RadGridView>public class RequestColumnConverter : IValueConverter{ public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value != null) { string name = (string)value; var requestImage = new Image() { Height = 16, Width = 16, HorizontalAlignment = System.Windows.HorizontalAlignment.Center, }; requestImage.Source = new BitmapImage(new Uri("pack://application:,,,/Images/service.png")); return requestImage; } else return null; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; }}<telerik:GridViewDataColumn Header="Type" IsReadOnly="True" UniqueName="SCSRequestTypeName" DataMemberBinding="{Binding Path=SCSRequestTypeName, Converter={StaticResource requestColumnConverter}}"> <telerik:GridViewDataColumn.CellTemplate> <DataTemplate> <Image Source="{Binding SCSRequestTypeName, Converter={StaticResource requestColumnConverter}}"/> </DataTemplate> </telerik:GridViewDataColumn.CellTemplate></telerik:GridViewDataColumn>
<UserControl x:Class="CarSystem.CustomControls.NumberSpinner" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" xmlns:cs="clr-namespace:CarSystem.CustomControls" mc:Ignorable="d" Focusable="True" Loaded="UserControl_Loaded"> <Grid Background="{Binding Path=GridBackground, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" Width="{Binding Path=Width, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <telerik:RadMaskedNumericInput BorderBrush="{Binding Path=BorderBrush, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" FlowDirection="{Binding Path=FlowDirection, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" Focusable="True" FontFamily="{Binding Path=FontFamily, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" FontSize="{Binding Path=FontSize, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" FontStretch="{Binding Path=FontStretch, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" FontStyle="{Binding Path=FontStyle, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" FontWeight="{Binding Path=FontWeight, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" GotFocus="ValueBox_GotFocus" Grid.Column="0" HorizontalAlignment="Stretch" HorizontalContentAlignment="Right" InputBehavior="Insert" IsClearButtonVisible="False" LostFocus="ValueBox_LostFocus" Margin="5" Mask="{Binding Path=Mask, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" Name="ValueBox" SelectionOnFocus="CaretToEnd" SpinMode="PositionAndValue" TabIndex="{Binding Path=TabIndex, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" TextMode="PlainText" UpdateValueEvent="PropertyChanged" Value="{Binding Path=Value, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" VerticalAlignment="Center" /> <RepeatButton Background="{DynamicResource ButtonBackground}" Click="IncrementButton_Click" Focusable="False" Foreground="{DynamicResource ButtonForeground}" Grid.Column="1" IsTabStop="False" Name="IncrementButton"> <Image> <Image.Style> <Style TargetType="{x:Type Image}"> <Setter Property="Source" Value="/CustomControls;component/Resources/VolumeUpDay.png" /> <Style.Triggers> <DataTrigger Binding="{Binding Path=TimeOfDayMode, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" Value="NightTime"> <Setter Property="Source" Value="/CustomControls;component/Resources/VolumeUpNight.png" /> </DataTrigger> </Style.Triggers> </Style> </Image.Style> </Image> </RepeatButton> <RepeatButton Background="{DynamicResource ButtonBackground}" Click="DecrementButton_Click" Focusable="False" Foreground="{DynamicResource ButtonForeground}" Grid.Column="2" IsTabStop="False" Name="DecrementButton"> <Image> <Image.Style> <Style TargetType="{x:Type Image}"> <Setter Property="Source" Value="/CustomControls;component/Resources/VolumeDnDay.png" /> <Style.Triggers> <DataTrigger Binding="{Binding Path=TimeOfDayMode, RelativeSource={RelativeSource AncestorType={x:Type cs:NumberSpinner}}}" Value="NightTime"> <Setter Property="Source" Value="/CustomControls;component/Resources/VolumeDnNight.png" /> </DataTrigger> </Style.Triggers> </Style> </Image.Style> </Image> </RepeatButton> </Grid> </UserControl> using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace CarSystem.CustomControls { public partial class NumberSpinner : UserControl { public static readonly DependencyProperty FocusedBackgroundProperty = DependencyProperty.Register( "FocusedBackground", typeof( Brush ), typeof( NumberSpinner ), new PropertyMetadata( null ) ); public static readonly DependencyProperty FocusedForegroundProperty = DependencyProperty.Register( "FocusedForeground", typeof( Brush ), typeof( NumberSpinner ), new PropertyMetadata( null ) ); public static DependencyProperty GridBackgroundProperty = DependencyProperty.Register( "GridBackground", typeof( Brush ), typeof( NumberSpinner ), new PropertyMetadata( Brushes.Transparent ) ); public static readonly DependencyProperty IncrementProperty = DependencyProperty.Register( "Increment", typeof( double ), typeof( NumberSpinner ), new PropertyMetadata( 1.0 ) ); public static readonly DependencyProperty MaskProperty = DependencyProperty.Register( "Mask", typeof( string ), typeof( NumberSpinner ), new PropertyMetadata( "#9.2" ) ); public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register( "Maximum", typeof( double ), typeof( NumberSpinner ), new PropertyMetadata( double.NaN, new PropertyChangedCallback( OnMaximumInvalidated ) ) ); public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register( "Minimum", typeof( double ), typeof( NumberSpinner ), new PropertyMetadata( double.NaN, new PropertyChangedCallback( OnMinimumInvalidated ) ) ); public static readonly DependencyProperty TimeOfDayModeProperty = DependencyProperty.Register( "TimeOfDayMode", typeof( TimesOfDay ), typeof( NumberSpinner ), new FrameworkPropertyMetadata( TimesOfDay.DayTime, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback( OnTimeOfDayInvalidated ) ) ); public static readonly DependencyProperty UnfocusedBackgroundProperty = DependencyProperty.Register( "UnfocusedBackground", typeof( Brush ), typeof( NumberSpinner ), new PropertyMetadata( null ) ); public static readonly DependencyProperty UnfocusedForegroundProperty = DependencyProperty.Register( "UnfocusedForeground", typeof( Brush ), typeof( NumberSpinner ), new PropertyMetadata( null ) ); public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( double ), typeof( NumberSpinner ), new PropertyMetadata( 0.0, new PropertyChangedCallback( OnValueInvalidated ) ) ); public Brush FocusedBackground { get { return (Brush) GetValue( FocusedBackgroundProperty ); } set { SetValue( FocusedBackgroundProperty, value ); } } public Brush FocusedForeground { get { return (Brush) GetValue( FocusedForegroundProperty ); } set { SetValue( FocusedForegroundProperty, value ); } } public Brush GridBackground { get { return (Brush) GetValue( GridBackgroundProperty ); } set { SetValue( GridBackgroundProperty, value ); } } public double Increment { get { return (double) GetValue( IncrementProperty ); } set { SetValue( IncrementProperty, value ); } } public string Mask { get { return (string) GetValue( MaskProperty ); } set { SetValue( MaskProperty, value ); } } public double Maximum { get { return (double) GetValue( MaximumProperty ); } set { SetValue( MaximumProperty, value ); } } public double Minimum { get { return (double) GetValue( MinimumProperty ); } set { SetValue( MinimumProperty, value ); } } public TimesOfDay TimeOfDayMode { get { return (TimesOfDay) GetValue( TimeOfDayModeProperty ); } set { SetValue( TimeOfDayModeProperty, value ); } } public Brush UnfocusedBackground { get { return (Brush) GetValue( UnfocusedBackgroundProperty ); } set { SetValue( UnfocusedBackgroundProperty, value ); } } public Brush UnfocusedForeground { get { return (Brush) GetValue( UnfocusedForegroundProperty ); } set { SetValue( UnfocusedForegroundProperty, value ); } } public double Value { get { return (double) GetValue( ValueProperty ); } set { SetValue( ValueProperty, value ); } } public NumberSpinner() { InitializeComponent(); } private void DecrementButton_Click( object sender, RoutedEventArgs e ) { Value -= Increment; } private void IncrementButton_Click( object sender, RoutedEventArgs e ) { Value += Increment; } private void OnMaximumChanged( double newMaximum ) { if ( !double.IsNaN( newMaximum ) ) { if ( Value > newMaximum ) { Value = newMaximum; } IncrementButton.IsEnabled = Value < newMaximum; } } private static void OnMaximumInvalidated( DependencyObject d, DependencyPropertyChangedEventArgs e ) { NumberSpinner spinner = d as NumberSpinner; spinner.OnMaximumChanged( (double) e.NewValue ); } private void OnMinimumChanged( double newMinimum ) { if ( !double.IsNaN( newMinimum ) ) { if ( Value < newMinimum ) { Value = newMinimum; } DecrementButton.IsEnabled = Value > newMinimum; } } private static void OnMinimumInvalidated( DependencyObject d, DependencyPropertyChangedEventArgs e ) { NumberSpinner spinner = d as NumberSpinner; spinner.OnMinimumChanged( (double) e.NewValue ); } private void OnTimeOfDayModeChanged( TimesOfDay newTimeofDayMode ) { if ( FocusedBackground != null && UnfocusedBackground != null ) { ValueBox.Background = ValueBox.IsFocused ? FocusedBackground : UnfocusedBackground; } if ( FocusedForeground != null && UnfocusedForeground != null ) { ValueBox.Foreground = ValueBox.IsFocused ? FocusedForeground : UnfocusedForeground; } } private static void OnTimeOfDayInvalidated( DependencyObject d, DependencyPropertyChangedEventArgs e ) { NumberSpinner spinner = (NumberSpinner) d; spinner.OnTimeOfDayModeChanged( (TimesOfDay) e.NewValue ); } private void OnValueChanged( double newValue ) { if ( ! double.IsNaN( Minimum ) ) { if ( newValue < Minimum ) { Value = Minimum; } DecrementButton.IsEnabled = Value > Minimum; } if ( ! double.IsNaN( Maximum ) ) { if ( Value > Maximum ) { Value = Maximum; } IncrementButton.IsEnabled = Value < Maximum; } } private static void OnValueInvalidated( DependencyObject d, DependencyPropertyChangedEventArgs e ) { NumberSpinner spinner = d as NumberSpinner; spinner.OnValueChanged( (double) e.NewValue ); } private void UserControl_Loaded( object sender, RoutedEventArgs e ) { if ( FocusedBackground == null && UnfocusedBackground == null ) { ValueBox.Background = Background; } if ( FocusedForeground == null && UnfocusedForeground == null ) { ValueBox.Foreground = Foreground; } } private void ValueBox_GotFocus( object sender, RoutedEventArgs e ) { if ( FocusedBackground != null ) { ValueBox.Background = FocusedBackground; } if ( FocusedForeground != null ) { ValueBox.Foreground = FocusedForeground; } } private void ValueBox_LostFocus( object sender, RoutedEventArgs e ) { if ( UnfocusedBackground != null ) { ValueBox.Background = UnfocusedBackground; } if ( UnfocusedForeground != null ) { ValueBox.Foreground = UnfocusedForeground; } } } }