This is a migrated thread and some comments may be shown as answers.

Problem with custom filter with custom type

8 Answers 266 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Mads
Top achievements
Rank 1
Mads asked on 14 Jan 2015, 09:14 AM
I am trying to use a custom type in my filter where I want to show all distinct versions of my type in the list, and this works! 


But when I select a value and try to filter on that value I get an error

var filter = new FilterDescriptor(dataMember, FilterOperator.IsEqualTo, checkBoxCustomFilterType.Text);

filter has the value "{PTestType IsEqualTo ks k}" where "ks k" is one of my distint values but its like the PTestType is not converted using the typeconverter? Because then this is thrown 

An exception of type 'System.ArgumentException' occurred in mscorlib.dll but was not handled in user code

Additional information: The value "(PTestType IsEqualTo ks k)" is not of type "Telerik.Windows.Data.IFilterDescriptor" and cannot be used in this generic collection.



Custom type Class

namespace Systematic.KVK.InseminationPlan.UIL.Details.Windows.TestBucket.DOM
{
    [TypeConverter(typeof(TestTypeConverter))]
    public class PTestType : IEquatable<PTestType>
    {
        public long Id { get; set; }
        public string ShortTestName { get; set; }
        public string TestName { get; set; }
 
        public bool Equals(PTestType other)
        {
            return Id == other.Id;
        }
 
        public override string ToString()
        {
            return ShortTestName;
        }
 
        public override int GetHashCode()
        {
            return (int)Id;
        }
 
        public override bool Equals(object obj)
        {
            var type = obj as PTestType;
            if (type != null)
            {
                return Id == type.Id;
            }
 
            return false;
        }
 
        bool IEquatable<PTestType>.Equals(PTestType other)
        {
            if (other == null)
            {
                return false;
            }
 
            return StringComparer.Ordinal.Equals(Id, other.Id);
        }
    }
}


Type converter and valueconverter

namespace Systematic.KVK.InseminationPlan.UIL.Details.Windows.TestBucket.Tabs.TestBucketTab
{
    public class PTestTypeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var TestType = (PTestType)value;
 
            return TestType.ShortTestName;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
 
    public class TestTypeConverter : TypeConverter
    {
        public TestTypeConverter()
        {
             
        }
 
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }
 
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            var stringValue = value as string;
            if (stringValue != null)
            {
                return new PTestType {Id = 1, TestName = "sdfsdf",ShortTestName = "shortsd"};
            }
 
            return base.ConvertFrom(context, culture, value);
        }
 
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return true;
            }
 
            return base.CanConvertTo(context, destinationType);
        }
 
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return ((PTestType)value).ShortTestName;
            }
 
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }
}


My Custom filter codebehind

namespace Systematic.KVK.InseminationPlan.UIL.Details.Windows.TestBucket.CustomFilters
{
    public partial class TestTypeCheckBoxFilterControl : IFilteringControl
    {
        public ObservableCollection<CheckBoxCustomFilterType> CustomItems { get; set; }
        private GridViewBoundColumnBase column;
        private CompositeFilterDescriptor compositeFilter;
 
        public TestTypeCheckBoxFilterControl()
        {
            InitializeComponent();
            CustomItems = new ObservableCollection<CheckBoxCustomFilterType>();
             
            DataContext = this;
        }
 
        private void OnFilter(object sender, RoutedEventArgs e)
        {
            column.DataControl.FilterDescriptors.Clear();
            compositeFilter = new CompositeFilterDescriptor {LogicalOperator = FilterCompositionLogicalOperator.Or};
            var dataMember = column.DataMemberBinding.Path.Path;
            foreach (var checkBoxCustomFilterType in CustomItems)
            {
                if (checkBoxCustomFilterType.Checked)
                {
                    var filter = new FilterDescriptor(dataMember, FilterOperator.IsEqualTo, checkBoxCustomFilterType.Text);
                    compositeFilter.FilterDescriptors.Add(filter);
                }
            }
 
            if (!column.DataControl.FilterDescriptors.Contains(compositeFilter))
            {
                column.DataControl.FilterDescriptors.Add(compositeFilter);
            }
 
            IsActive = true;
        }
 
        private void OnClear(object sender, RoutedEventArgs e)
        {
            column.DataControl.FilterDescriptors.Clear();
            compositeFilter.FilterDescriptors.Clear();
            CustomItems.ForEach(x => x.Checked = false);
        }
 
        public void Prepare(Telerik.Windows.Controls.GridViewColumn column)
        {
            CustomItems.Clear();
 
            this.column = column as GridViewBoundColumnBase;
 
 
 
            var distinctValues = ((RadGridView)column.Parent).GetDistinctValues(column, false);
 
            foreach (PTestType distinctValue in distinctValues)
            {
                CustomItems.Add(new CheckBoxCustomFilterType {Checked = false, Text = distinctValue.ToString()});
            }
        }
 
        public bool IsActive { get; set; }
 
        private void SelectAll(object sender, RoutedEventArgs e)
        {
            var checkbox = (sender as CheckBox);
            if (checkbox == null || checkbox.IsChecked == null)
            {
                return;
            }
 
            foreach (var checkBoxCustomFilterType in CustomItems)
            {
                checkBoxCustomFilterType.Checked = checkbox.IsChecked.Value;
            }
        }
    }
}


My usages of my custom filter

<telerik:GridViewDataColumn
    DataMemberBinding="{Binding Path=PTestType}"
    IsReadOnly="True"
    IsFilterable="True"
    Header="{x:Static localization:TestBucketTexts.TestType}">
    <telerik:GridViewDataColumn.FilteringControl>
        <customFilters:TestTypeCheckBoxFilterControl />
    </telerik:GridViewDataColumn.FilteringControl>
    <telerik:GridViewDataColumn.CellTemplate>
        <DataTemplate DataType="dom:PBucketModel">
            <TextBlock
                Text="{Binding Path=PTestType}" />
        </DataTemplate>
    </telerik:GridViewDataColumn.CellTemplate>
</telerik:GridViewDataColumn>

8 Answers, 1 is accepted

Sort by
0
Mads
Top achievements
Rank 1
answered on 16 Jan 2015, 10:00 AM
Any help with this?
-1
Dimitrina
Telerik team
answered on 16 Jan 2015, 03:12 PM
Hi,

The error message says that "(PTestType IsEqualTo ks k)" is not a valid IFilterDescriptor. Generally, I would suggest you defining a custom filtering control instead, you can find the Custom Filtering Controls article for more details.

You can also refer to this forum thread on Persisting Column Filter where a similar exception was already discussed.

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
Mads
Top achievements
Rank 1
answered on 19 Jan 2015, 07:44 AM
Dimitrina I am already using a custom filter TestTypeCheckBoxFilterControl (The code is in the first post) and I cant get it working, it works fine if my type is string or int, but my custom class do not work and gives me that error
0
Boris
Telerik team
answered on 21 Jan 2015, 03:22 PM
Hello,

Without a provide us with a small runnable project that reproduces your issue, we would be only guessing as to why the  mentioned error occurs. By providing us with such a project we will be able to debug it on our side and be more accurate in our findings. In addition, if you are not entirely sure how to isolate it, you can check this Isolating a problem in a sample project  blog post for some guidance.


Regards,
Boris
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
Mads
Top achievements
Rank 1
answered on 22 Jan 2015, 09:38 AM
https://dl.dropboxusercontent.com/u/19153690/TelerikCustomFilter.zip

The exception is thrown when I try to filter by SomeType

Also I am in doubt how I am supposed to do this line correctly

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
    var stringValue = value as string;
    if (stringValue != null)
    {
        return new SomeType { Id = 1, SomeTypeName = "sdfsdf", ShortSomeTypeName= "shortsd" };
    }
 
    return base.ConvertFrom(context, culture, value);
}
0
Boris
Telerik team
answered on 26 Jan 2015, 04:42 PM
Hi,

Thank you for the provided project . As it turns out the issue was that you we trying to filter a specific column by a value different than the underlying bound data type. For example your "Some type short name" column is bound to the SomeType property of type SomeType and then you try to filter it by a property of type string. In order to make this work I made the following changes: 

1) Added a property of type object in your CheckBoxCustomFilterType class. The type is object because your CheckBoxFilterControl control is used for properties of different types (long and SomeType).

public class CheckBoxCustomFilterType : NotifiableObject
    {
        ...
         
        private object internalSomeType;
        public object InternalSomeType
        {
            get
            {
                return this.internalSomeType;
            }
            set
            {
                if (this.internalSomeType != value)
                {
                    this.internalSomeType = value;
                    RaisePropertyChanged(() => InternalSomeType);
                }
            }
        }   
         ...   
    }
}


2) Updated the Prepare() method of the CheckBoxFilterControl control to pass the distinct value to the newly created property.

public void Prepare(Telerik.Windows.Controls.GridViewColumn column)
     {
         CustomItems.Clear();
 
         this._column = column as GridViewBoundColumnBase;
 
         var distinctValues = ((RadGridView)column.Parent).GetDistinctValues(column, false);
 
         foreach (object distinctValue in distinctValues)
         {
             CustomItems.Add(new CheckBoxCustomFilterType { Checked = false, Text = distinctValue.ToString(), InternalSomeType = distinctValue });
         }
     }


3) Updated the OnFilter() method to add the correct filter value in the FilterDescriptor constructor:

private void OnFilter(object sender, RoutedEventArgs e)
       {
           if (_compositeFilter != null)
           {
               _column.DataControl.FilterDescriptors.Remove(_compositeFilter);
           }
 
           _compositeFilter = new CompositeFilterDescriptor { LogicalOperator = FilterCompositionLogicalOperator.Or };
           var dataMember = _column.DataMemberBinding.Path.Path;
           foreach (var checkBoxCustomFilterType in CustomItems)
           {
               if (checkBoxCustomFilterType.Checked)
               {
                   var filter = new FilterDescriptor(dataMember, FilterOperator.IsEqualTo, checkBoxCustomFilterType.InternalSomeType);
                   _compositeFilter.FilterDescriptors.Add(filter);
               }
           }
 
           if (!_column.DataControl.FilterDescriptors.Contains(_compositeFilter))
           {
               _column.DataControl.FilterDescriptors.Add(_compositeFilter);
           }
 
           IsActive = true;
       }

I attached an updated version of your project that demonstrates the suggested approach.

I hope this helps.

Regards,
Boris
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
Mads
Top achievements
Rank 1
answered on 03 Feb 2015, 09:11 AM
Fantastic! One last request for now, how can I get the fitler window to close when I click filter or clear?
0
Boris
Telerik team
answered on 04 Feb 2015, 12:48 PM
Hi,

In order to close the filtering popup of the your custom filtering control when you press the Filer or Clear button, you will need to set its IsOpen property to false in their corresponding event handlers:

private void OnFilter(object sender, RoutedEventArgs e)
        {
           ...
 
            var popup = this.ParentOfType<System.Windows.Controls.Primitives.Popup>();
            if (popup != null)
            {
                popup.IsOpen = false;
            }
        }
 
        private void OnClear(object sender, RoutedEventArgs e)
        {
            ...
            var popup = this.ParentOfType<System.Windows.Controls.Primitives.Popup>();
            if (popup != null)
            {
                popup.IsOpen = false;
            }
        }

A possible way to find the filtering Popup is to use the ParentOfType<T>() extension method.


Regards,
Boris
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.

 
Tags
GridView
Asked by
Mads
Top achievements
Rank 1
Answers by
Mads
Top achievements
Rank 1
Dimitrina
Telerik team
Boris
Telerik team
Share this question
or