This question is locked. New answers and comments are not allowed.
Hello,
In our application we are using the CustomFilterRow on every grid so the users can easily filter these grids. Our application is based on the MVVM principle. This had some complications for the CustomFilterRow (http://demos.telerik.com/silverlight/#GridView/CustomFilterRow). I would like to sum them up and check if other users also dealt with these issues, so that Telerik might improve the CustomFilterRow in future releases, or just to get some feedback from Telerik whether all the issues are dealt with properly.
1. DataTypes for columns are not known
Problem: We are using a DomainDataSource that is exposed by the ViewModel. The GridView is bound to a collection of entities in the ViewModel. When we just attach the CustomFilterRow via telerikGridViewFilter:CustomFilterRow.IsEnabled="True" than it will try to create the specific ColumnHeaders based on the DataType of each column. This happens in the FilteringRow_Loaded callback method. The issue here is, that the datatypes are not known in this callback method.
Solution: Use the GridView's DataLoaded event to create the ColumnHeaders. We've changed this in the contructor for CustomFilterRow. If you just set the CustomFilterRow.IsEnabled= true in the GridView's DataLoaded event, then the filtering row is not drawn.
(CustomFilterRow.cs)
2. The CustomFilterRow was always indented wrong
Problem: The FilterRow was always indented to the right. The filteringRow adds a rowindicator in its first column, without checking whether the GridView has RowIndicatorVisibility set to true.
Solution: (CustomFilterRow.cs)
3. Changed the contextmenu for every FilterColumnHeader
Problem: There was no way for the user to see what filteroperator is being used to filter the grid. The only visual cue the user has, was whether he is filtering or not. (filtericon lit up or not). On top of that, the items in the context menu were not translated.
Solution: We've created our own FilterMenuItem class which is used in the ItemsSource of the RadContextMenu. This FilterMenuItem has a property IsChecked we can use via a Telerik ContainerBinding in the itemssource. (I've tried to use the RadMenuItem to achieve this, but I wasn't allowed to use a RadMenuItem in a DataTemplate). Now the user can see in the context menu which filteroperator is being used.
(FilterMenuItem.cs)
(TextColumnHeader.xaml)
(ColumnFilterCell.cs)
4. NullPointerExceptions when trying to filter on a DateTime column
Problem: When clicking an item in the contextmenu for a column with datatype=datetime, a nullpointer exception was thrown when no datetime was filled in.
Solution: Override OnFilterDescriptorChanged and set the Value of the filter to DateTime.Now by default.
(DateTimeColumnHeader.xaml.cs)
5. Could not tab out of NumericColumnFilter
Problem: Only certain keys were allowed to be used in NumericColumnFilter.
Solution: Changed the eventhandler to check which keys were pressed, and changed the textbox by a telerik maskedtextbox.
(NumericColumnHeader.xaml)
I hope this was clear and that it provides Telerik some feedback on the way the FilteringRow is used in a real-life sample.
Kind regards,
Sodi We
In our application we are using the CustomFilterRow on every grid so the users can easily filter these grids. Our application is based on the MVVM principle. This had some complications for the CustomFilterRow (http://demos.telerik.com/silverlight/#GridView/CustomFilterRow). I would like to sum them up and check if other users also dealt with these issues, so that Telerik might improve the CustomFilterRow in future releases, or just to get some feedback from Telerik whether all the issues are dealt with properly.
1. DataTypes for columns are not known
Problem: We are using a DomainDataSource that is exposed by the ViewModel. The GridView is bound to a collection of entities in the ViewModel. When we just attach the CustomFilterRow via telerikGridViewFilter:CustomFilterRow.IsEnabled="True" than it will try to create the specific ColumnHeaders based on the DataType of each column. This happens in the FilteringRow_Loaded callback method. The issue here is, that the datatypes are not known in this callback method.
Solution: Use the GridView's DataLoaded event to create the ColumnHeaders. We've changed this in the contructor for CustomFilterRow. If you just set the CustomFilterRow.IsEnabled= true in the GridView's DataLoaded event, then the filtering row is not drawn.
(CustomFilterRow.cs)
public CustomFilterRow(RadGridView radGridView) |
{ |
this.radGridView = radGridView; |
this.radGridView.IsFilteringAllowed = false; |
this.filteringRow = new FilteringRow(); |
//use the DataLoaded event, because column datatypes are not known yet |
//this.filteringRow.Loaded += this.FilteringRow_Loaded; |
this.radGridView.DataLoaded += radGridView_DataLoaded; |
this.radGridView.RowLoaded += this.radGridView_RowLoaded; |
this.radGridView.ColumnDisplayIndexChanged += this.ReorderFilterCells; |
this.radGridView.Grouped += this.RecalculateIndentPresenterWidth; |
} |
2. The CustomFilterRow was always indented wrong
Problem: The FilterRow was always indented to the right. The filteringRow adds a rowindicator in its first column, without checking whether the GridView has RowIndicatorVisibility set to true.
Solution: (CustomFilterRow.cs)
private void radGridView_RowLoaded(object sender, RowLoadedEventArgs e) |
{ |
if (e.Row is GridViewHeaderRow) |
{ |
Grid rootPanelGrid = (from c in this.radGridView.ChildrenOfType<Grid>() |
where c.Name == "PART_RootPanel" |
select c).FirstOrDefault(); |
if (rootPanelGrid != null && this.filteringRow.Parent == null) |
{ |
rootPanelGrid.Loaded += this.rootPanelGrid_Loaded; |
} |
//added extra check to only add the indicator when the grid has one |
if (radGridView.RowIndicatorVisibility == Visibility.Visible) |
{ |
Border indicator = (from c in this.radGridView.ChildrenOfType<Border>() |
where c.Name == "PART_IndicatorPresenter" |
select c).FirstOrDefault(); |
if (indicator != null) |
{ |
this.filteringRow.CustomFilterRowRoot.ColumnDefinitions[0].Width = new GridLength(indicator.Width); |
} |
} |
} |
} |
3. Changed the contextmenu for every FilterColumnHeader
Problem: There was no way for the user to see what filteroperator is being used to filter the grid. The only visual cue the user has, was whether he is filtering or not. (filtericon lit up or not). On top of that, the items in the context menu were not translated.
Solution: We've created our own FilterMenuItem class which is used in the ItemsSource of the RadContextMenu. This FilterMenuItem has a property IsChecked we can use via a Telerik ContainerBinding in the itemssource. (I've tried to use the RadMenuItem to achieve this, but I wasn't allowed to use a RadMenuItem in a DataTemplate). Now the user can see in the context menu which filteroperator is being used.
(FilterMenuItem.cs)
public class FilterMenuItem : ViewModelBase |
{ |
private string header; |
private bool isChecked; |
public bool IsChecked |
{ |
get |
{ |
return isChecked; |
} |
set |
{ |
if (isChecked == value) |
return; |
isChecked = value; |
NotifyPropertyChanged("IsChecked"); |
} |
} |
public string Header |
{ |
get |
{ |
return header; |
} |
set |
{ |
if (header == value) |
return; |
header = value; |
NotifyPropertyChanged("Header"); |
} |
} |
public object Tag { get; set; } |
} |
(TextColumnHeader.xaml)
<local:ColumnFilterCell x:Class="XXX.TextColumnHeader" |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
xmlns:telerikNavigation="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation" |
xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls" |
xmlns:local="clr-namespace:XXX.CustomFilterRow"> |
<UserControl.Resources> |
<telerik:ContainerBindingCollection x:Key="ContainerBindings"> |
<telerik:ContainerBinding PropertyName="IsChecked" |
Binding="{Binding IsChecked, Mode=TwoWay}" /> |
</telerik:ContainerBindingCollection> |
<DataTemplate x:Key="ItemTemplate" |
telerik:ContainerBinding.ContainerBindings="{StaticResource ContainerBindings}"> |
<TextBlock Text="{Binding Header}" /> |
</DataTemplate> |
</UserControl.Resources> |
<Border> |
<Grid> |
<Grid.ColumnDefinitions> |
<ColumnDefinition Width="*"/> |
<ColumnDefinition Width="Auto"/> |
</Grid.ColumnDefinitions> |
<TextBox Name="tbValue" Grid.Column="0" Text="{Binding FilterDescriptor.Value, Mode=TwoWay}" HorizontalAlignment="Stretch" TextChanged="TextBox_TextChanged"/> |
<ContentControl Grid.Column="1" Content="{Binding FilterVisibility}"> |
<telerikNavigation:RadContextMenu.ContextMenu> |
<telerikNavigation:RadContextMenu Name="filterContextMenu" ItemClick="filterContextMenu_ItemClick" ItemsSource="{Binding FilterOperators}" EventName="MouseLeftButtonUp" ItemTemplate="{StaticResource ItemTemplate}" /> |
</telerikNavigation:RadContextMenu.ContextMenu> |
</ContentControl> |
</Grid> |
</Border> |
</local:ColumnFilterCell> |
(ColumnFilterCell.cs)
... |
//Adds the FilterMenuItems to be used in the ContextMenu for every ColumnHeader |
public void SetFilterDescriptors() |
{ |
_filterOperatorMenuItems = new List<FilterMenuItem>(); |
//Add the "No Filter" menu item |
_filterOperatorMenuItems.Add(this.CreateFilterMenuItem(ActionResources.ResourceManager.GetString(String.Format("FilterOperator{0}", "NoFilter")))); |
foreach (System.Windows.Controls.FilterOperator filterOperator in this.FilterDescriptor.MemberType.GetApplicableFilterOperators()) |
{ |
_filterOperatorMenuItems.Add(CreateFilterMenuItem(ActionResources.ResourceManager.GetString(String.Format("FilterOperator{0}", filterOperator.ToString())), filterOperator)); |
} |
} |
... |
/// <summary> |
/// Callback method for when a filterMenuItem has been clicked. This method |
/// will check the current filterDescriptor in the menu so user can see what |
/// type of filtering is being applied. |
/// </summary> |
/// <param name="menuItem"></param> |
protected void OnFilterMenuItemClick(FilterMenuItem menuItem) |
{ |
if (menuItem != null) |
{ |
var item = (FilterMenuItem)menuItem; |
item.IsChecked = true; |
UncheckOtherMenuItems(item); |
if (item.Tag != null) |
{ |
this.FilterDescriptor.Operator = (FilterOperator)item.Tag; |
this.IsFilterActive = true; |
} |
else |
{ |
this.IsFilterActive = false; |
} |
} |
} |
4. NullPointerExceptions when trying to filter on a DateTime column
Problem: When clicking an item in the contextmenu for a column with datatype=datetime, a nullpointer exception was thrown when no datetime was filled in.
Solution: Override OnFilterDescriptorChanged and set the Value of the filter to DateTime.Now by default.
(DateTimeColumnHeader.xaml.cs)
protected override void OnFilterDescriptorChanged(Telerik.Windows.Data.FilterDescriptor oldValue, Telerik.Windows.Data.FilterDescriptor newValue) |
{ |
base.OnFilterDescriptorChanged(oldValue, newValue); |
if (newValue != null) |
{ |
newValue.Value = DateTime.Now; |
} |
} |
5. Could not tab out of NumericColumnFilter
Problem: Only certain keys were allowed to be used in NumericColumnFilter.
Solution: Changed the eventhandler to check which keys were pressed, and changed the textbox by a telerik maskedtextbox.
(NumericColumnHeader.xaml)
<!--<TextBox Grid.Column="0" Text="{Binding FilterDescriptor.Value, Mode=TwoWay}" KeyDown="TextBoxKeyDown" />--> |
<telerikInput:RadMaskedTextBox Name="tbValue" Grid.Column="0" MaskType="Numeric" Mask="d" Value="{Binding FilterDescriptor.Value, Mode=TwoWay}" SelectionOnFocus="SelectAll" ValueChanged="tbValue_ValueChanged" /> |
I hope this was clear and that it provides Telerik some feedback on the way the FilteringRow is used in a real-life sample.
Kind regards,
Sodi We