In the screenshot attached, lets say that i have Jones, Trent as a value in that column on multiple rows. I want the "selection list" to only show the values (without semicolon) and only show Jones, Trent once.
Thanks.
11 Answers, 1 is accepted
It is not a good approach to override the list with checkboxes in the default filter box as the filtering will not find any results on this new values that you have (unless you have cells with exact the same value). Filtering is using "==" to compare the values from the check boxes with the values in the cells and it will filter only on exact match.
Filtering in this way may have many unwanted consequences because the filtering mechanism and UI is not supposed to work that way.
What is the way to go is to use the standard way of filtering or create a custom filtering control which will be able to handle this specific case. There you may use a ColumnFilterDescriptor with operator Contains for the string values in the check boxes.
I hope that this helps.
Didie
the Telerik team
1. used DistinctValuesLoading to change the Distinct values list for a particular column.
2. used Attached behavior to change "IsEqualTo" to "Contains"
3. clicking apply filter does the work.
My last issue is how to change the UI so that when you click a distinct value checkbox (which does the filtering on the fly) that it changes the grid like clicking "apply filter" does.
Clicking on a distinct value will automatically filter the grid immediately and this is the default behavior of our grid so I am not sure what you are doing. You can see this behavior on all of our online examples.
Also, how did you manage to alter the underlying FilterDescriptor that sits behind the distinct value and change its FilterOperator from IsEqualTo to Contains? Could you please elaborate? Are you using your own custom filtering control or the stock one?
I am looking forward to hearing from you.
Ross
the Telerik team
void
radGridView1_DistinctValuesLoading(
object
sender, Telerik.Windows.Controls.GridView.GridViewDistinctValuesLoadingEventArgs e)
{
if
(e.Column.CanFilter() ==
true
&& (
string
)e.Column.Header ==
"Matters"
)
{
e.ItemsSource = _items.SelectMany(item => item.Matters.Select(matt => matt.Name)).Distinct();
// radGridView1.GetDistinctValues(e.Column, true, radGridView1.Items.Count);
}
}
Attached Behaviour
public
class
DistinctValuesUsingContainsBehavior : Behavior<GridViewBoundColumnBase>
{
FilteringControl customFilteringControl;
CheckBox selectAllDistinct;
Button applyFilterButton;
Button clearFilterButton;
System.Windows.Controls.ListBox distinctValuesList;
protected
override
void
OnAttached()
{
this
.customFilteringControl =
new
FilteringControl();
this
.customFilteringControl.Loaded +=
this
.OnFilteringControlLoaded;
this
.AssociatedObject.FilteringControl = customFilteringControl;
}
void
OnFilteringControlLoaded(
object
sender, RoutedEventArgs e)
{
// Find controls and associate events
this
.applyFilterButton =
this
.customFilteringControl
.ChildrenOfType<Button>()
.Where(b => b.Name ==
"PART_ApplyFilterButton"
)
.FirstOrDefault();
if
(
this
.applyFilterButton !=
null
)
{
this
.applyFilterButton.Click +=
this
.OnApplyFilter;
}
this
.clearFilterButton =
this
.customFilteringControl
.ChildrenOfType<Button>()
.Where(b => b.Name ==
"PART_ClearFilterButton"
)
.FirstOrDefault();
if
(
this
.clearFilterButton !=
null
)
{
this
.clearFilterButton.Click +=
this
.OnClearFilter;
}
// Are distint filters permitted on this column
if
(
this
.customFilteringControl.DistinctFiltersVisibility == Visibility.Visible)
{
this
.selectAllDistinct =
this
.customFilteringControl
.ChildrenOfType<CheckBox>()
.Where(l => l.Name ==
"PART_SelectAllCheckBox"
)
.FirstOrDefault();
this
.selectAllDistinct.Checked +=
new
RoutedEventHandler(OnSelectAllChecked);
this
.selectAllDistinct.Unchecked +=
new
RoutedEventHandler(OnSelectAllUnchecked);
this
.distinctValuesList =
this
.customFilteringControl
.ChildrenOfType<System.Windows.Controls.ListBox>()
.Where(l => l.Name ==
"PART_DistinctValuesList"
)
.FirstOrDefault();
}
//this.applyFilterButton = this.customControl
// .ChildrenOfType<Button>()
// .Where(b => b.Name == "PART_ApplyFilterButton")
// .FirstOrDefault();
////PART_DistinctValuesList
//this.distinctValuesList = this.customControl
// .ChildrenOfType<System.Windows.Controls.ListBox>()
// .Where(b => b.Name == "PART_DistinctValuesList")
// .FirstOrDefault();
////FilteringViewModel m = newList.DataContext as FilteringViewModel;
////IEnumerable<Tuple<string[],bool>> data = m.DistinctValues.Select(dvm => new Tuple<string[],bool>(dvm.ConvertedValue.ToString().Split(';').ToArray<string>(), dvm.IsActive) );
//if (this.applyFilterButton != null)
//{
// this.applyFilterButton.Click += this.OnApplyFilter;
//}
}
void
OnSelectAllChecked(
object
sender, RoutedEventArgs e)
{
SelectAll(
true
);
}
void
OnSelectAllUnchecked(
object
sender, RoutedEventArgs e)
{
SelectAll(
false
);
}
private
void
SelectAll(
bool
check)
{
if
(
this
.selectAllDistinct !=
null
&&
this
.distinctValuesList !=
null
)
{
// Check / uncheck items
var chks =
this
.distinctValuesList.ChildrenOfType<CheckBox>();
foreach
(var chk
in
chks)
{
chk.IsChecked = check;
}
// Set view model property
((FilteringViewModel)
this
.customFilteringControl.DataContext).SelectAll = check;
}
}
public
void
OnApplyFilter(
object
sender, RoutedEventArgs e)
{
if
(
this
.customFilteringControl.DistinctFiltersVisibility == Visibility.Visible &&
this
.distinctValuesList !=
null
)
{
ColumnFilterDescriptor columnDescriptor;
bool
addDesc =
false
;
var descriptor =
this
.AssociatedObject.DataControl.FilterDescriptors
.Where(desc => ((ColumnFilterDescriptor)desc).Column.GetDataMemberName() ==
this
.AssociatedObject.GetDataMemberName())
.FirstOrDefault();
if
(descriptor ==
null
)
{
// Create new filter if we don't already have one
columnDescriptor =
new
ColumnFilterDescriptor((IDataFieldDescriptor)
this
.AssociatedObject.DataControl.Columns[
this
.AssociatedObject.DisplayIndex]);
addDesc =
true
;
}
else
{
// Clear distinct values filter from existing filter
columnDescriptor = (ColumnFilterDescriptor)descriptor;
//Expression
//columnDescriptor.DistinctFilter.FilterDescriptors[0].CreateFilterExpression()
columnDescriptor.DistinctFilter.DistinctValues.Clear();
}
var chks =
this
.distinctValuesList.ChildrenOfType<CheckBox>();
foreach
(var chk
in
chks)
{
if
(chk.IsChecked.HasValue && chk.IsChecked.Value)
{
if
(
this
.AssociatedObject.DataType ==
typeof
(
bool
))
{
if
(
string
.Compare(chk.Content.ToString().ToLower(),
"true"
) == 0)
{
columnDescriptor.DistinctFilter.DistinctValues.Add(
true
);
}
else
{
columnDescriptor.DistinctFilter.DistinctValues.Add(
false
);
}
}
else
{
columnDescriptor.DistinctFilter.DistinctValues.Add(chk.Content);
}
}
}
foreach
(FilterDescriptor x
in
columnDescriptor.DistinctFilter.FilterDescriptors)
{
x.Operator = FilterOperator.Contains;
}
if
(addDesc && columnDescriptor.DistinctFilter.DistinctValues.Count > 0)
{
this
.AssociatedObject.DataControl.FilterDescriptors.Add(columnDescriptor);
}
}
// And when clicked find the parent popup and close it.
var popup = applyFilterButton.ParentOfType<System.Windows.Controls.Primitives.Popup>();
if
(popup !=
null
)
{
popup.IsOpen =
false
;
}
}
void
OnClearFilter(
object
sender, RoutedEventArgs e)
{
// And when clicked find the parent popup and close it.
var popup = clearFilterButton.ParentOfType<System.Windows.Controls.Primitives.Popup>();
if
(popup !=
null
)
{
popup.IsOpen =
false
;
}
}
protected
override
void
OnDetaching()
{
if
(
this
.applyFilterButton !=
null
)
{
this
.applyFilterButton.Click -=
this
.OnApplyFilter;
}
if
(
this
.clearFilterButton !=
null
)
{
this
.clearFilterButton.Click -=
this
.OnClearFilter;
}
if
(
this
.selectAllDistinct !=
null
)
{
this
.selectAllDistinct.Checked -=
this
.OnSelectAllChecked;
this
.selectAllDistinct.Unchecked -=
this
.OnSelectAllUnchecked;
}
this
.customFilteringControl.Loaded -=
this
.OnFilteringControlLoaded;
}
}
Using behaviour
<
telerik:GridViewDataColumn
Header
=
"Matters"
DataMemberBinding
=
"{Binding MatterNames}"
ShowFieldFilters
=
"False"
ShowDistinctFilters
=
"False"
>
<
i:Interaction.Behaviors
>
<
my:DistinctValuesUsingContainsBehavior
/>
</
i:Interaction.Behaviors
>
</
telerik:GridViewDataColumn
>
MatterNames from view model:
public
string
MatterNames
{
get
{
return
string
.Join(
";"
, _matters.Select(mat => mat.Name));
}
}
Try it and you will see i still need to override the individual check boxes somehow.
I am a little bit shocked by this code.
You have taken our stock control and altered its built-in behaviour beyond recognition.
You have managed to change almost everything.
You are not supposed to interfere in its inner workings in this way.
You can't possibly expect things to work in this case and I can no longer guarantee that they will work, since this is not our control any-more. The fact that something is public, does not mean that it should be tampered with. In this case we had to make the view model public since Silverlight will complain otherwise. This does not mean that you should cast the DataContext to our view model class and start changing stuff.
The stock FilteringControl was designed to work in a certain way and interfering with its inner workings can render it useless.
I am afraid that I cannot support this "new" FilteringControl, since you have totally altered its built-in logic and this is no longer our FilteringControl.
My suggestion is to create your very own FilteringControl from scratch and weave any kind of custom logic that you want. You will be in charge of everything -- the UI, the view model that sits behind and the filtering logic. The idea is simple -- you provide the UI that you want to the end user, you respond to user actions over this UI and based on these action you add, removed or modify a ColumnFilterDescriptor like described in my blog post. This will be much easier for you than trying to make something work in a way it was not really designed for.
I hope this makes sense.
Ross
the Telerik team
However, this control, is exactly the same as the one mentioned here:
http://blogs.telerik.com/blogs/posts/10-01-22/how_to_customize_radgridview_s_default_filtering_control_with_attached_behaviors_silverlight_amp_wpf.aspx
with the addition of two things. "close when clear filter" and "contains" rather than "IsEqualTo"
The suggestion on the blog post is exactly what i was after. I wanted just to change "IsEqualTo" to contains. I don't care about the "close popup" on "fitler" or "Clear Filter".
Let me clean up the attached behavior to only do the "Contains" bit.
Reality is i copy-pasted all of that from another forum entry on your site minus these lines:
foreach
(FilterDescriptor x
in
columnDescriptor.DistinctFilter.FilterDescriptors)
{
x.Operator = FilterOperator.Contains;
}
http://www.telerik.com/community/forums/silverlight/gridview/selected-filter-not-showing-with-autogeneratecolumns-set-to-true.aspx
We can not support this kind of a custom solution taken from various blog and forum posts as a true genuine product.
Thank you for your understanding.
My suggestion is to create your very own FilteringControl from scratch and weave any kind of custom logic that you want. You will be in charge of everything -- the UI, the view model that sits behind and the filtering logic. The idea is simple -- you provide the UI that you want to the end user, you respond to user actions over this UI and based on these action you add, removed or modify a ColumnFilterDescriptor like described in my blog post. This will be much easier for you than trying to make something work in a way it was not really designed for.
Ross
the Telerik team
"Very often, however, you may be perfectly happy with the stock filtering control, but you wish you could modify and adapt it just a little bit to match your particular requirements. What should you do then?"
http://blogs.telerik.com/blogs/posts/10-01-22/how_to_customize_radgridview_s_default_filtering_control_with_attached_behaviors_silverlight_amp_wpf.aspx
I just want to change a small bit and still get Skinning, etc.
Great you don't recommend it. but you tell us how to do it. therefore it should be supported. I don't want to rewrite the entire control.
I am not sure how to explain this. The approach you have undertaken is not possible. The stock filtering control cannot operate in the way you expect it to. It was designed with another behavior at mind, and the one you want to achieve is simply not possible with it. It was not designed to perform the kind of filtering you want. There is nothing we can do to change that, since your requirement is quite custom and our stock control can not handle it. I hope this makes sense. Thank you for your understanding.
Regards,Ross
the Telerik team
Yes, I can do a customfilter, which a had already done. However i like this approach too as described by your own blog post.