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

ItemPropertyDefs in unbound mode

1 Answer 89 Views
DataFilter
This is a migrated thread and some comments may be shown as answers.
david mcintyre
Top achievements
Rank 1
david mcintyre asked on 05 May 2011, 02:01 PM
I have a problem getting the raddatafilter to work properly in unbound mode.  I want to use your datafilter to filter a DomainDataSource, which is in my viewmodel, so I created a custom control that inherits from RDF, and into which I pasted and adapted the code from the demo at http://demos.telerik.com/silverlight/#DataFilter/DomainDataSource .  Now I have two problems.  First, the user has to click twice on the remove button to remove a filter.   For example, if I've added a filter to filter the datagrid based on a particular ItemID, the first click on the "X" removes the filter from the DDS and the datagrid is refreshed.  But the filter is still present in the UI until the user clicks a 2nd time on the X.

The 2nd problem is that the DDS is not automatically refreshed when the filters and filter collection are altered.  I can workaround this by adding a Load method or a separate button that calls Load but I would prefer to see if there's a better way to do this.  Below is snippets of my xaml and my custom datafilter class.   
public class DatagridFilter: RadDataFilter
    {
        private Dictionary<Telerik.Windows.Data.FilterDescriptor, System.Windows.Controls.FilterDescriptor> filterMap
            = new Dictionary<Telerik.Windows.Data.FilterDescriptor, System.Windows.Controls.FilterDescriptor>();
        DomainDataSource dds;
  
        public DatagridFilter()
        {
            this.CanUserCreateCompositeFilters = false; 
            this.FilterDescriptors.PropertyChanged += this.OnFilterDescriptorsPropertyChanged;
  
            // Hook up the FilterDescriptors
            this.FilterDescriptors.CollectionChanged += this.OnFilterDescriptorsCollectionChanged;
  
  
            this.FilterOperatorsLoading += new EventHandler<FilterOperatorsLoadingEventArgs>(DatagridFilter_FilterOperatorsLoading);
        }
  
        void DatagridFilter_FilterOperatorsLoading(object sender, FilterOperatorsLoadingEventArgs e)
        
            Telerik.Windows.Data.FilterOperator f1 = Telerik.Windows.Data.FilterOperator.DoesNotContain;
            Telerik.Windows.Data.FilterOperator f2 = Telerik.Windows.Data.FilterOperator.IsContainedIn;
            Telerik.Windows.Data.FilterOperator f3 = Telerik.Windows.Data.FilterOperator.IsNotContainedIn;
            Telerik.Windows.Data.FilterOperator f4 = Telerik.Windows.Data.FilterOperator.EndsWith;
            //Telerik.Windows.Data.FilterOperator f4 = Telerik.Windows.Data.FilterOperator.Contains;
            e.AvailableOperators.Remove(f1);
            e.AvailableOperators.Remove(f2);
            e.AvailableOperators.Remove(f3);
            e.AvailableOperators.Remove(f4); 
        }
  
        private void OnFilterDescriptorsPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            ICompositeFilterDescriptor cfd = (ICompositeFilterDescriptor)sender;
            SetDDS(cfd);
            if (e.PropertyName == "LogicalOperator")
            {
                this.dds.FilterOperator = CreateRIALogicalOperator(cfd.LogicalOperator);
            }
        }
          
        void SetDDS(ICompositeFilterDescriptor cfd)
        {
            if (dds == null)
            {
                var vm = this.DataContext as IListBaseVM;
                if (vm != null)
                {
                    dds = vm.VMDatasource;
                    if (dds != null && dds.CanLoad)
                    {
                        dds.FilterOperator = CreateRIALogicalOperator(cfd.LogicalOperator);
                    }
                }
            }
        }
  
        private void OnFilterDescriptorsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            ICompositeFilterDescriptor cfd = (ICompositeFilterDescriptor)sender;
            SetDDS(cfd);
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (Telerik.Windows.Data.FilterDescriptor filterDescriptor
                        in e.NewItems.OfType<Telerik.Windows.Data.FilterDescriptor>())
                    {
                        this.AddFilter(filterDescriptor);
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    foreach (Telerik.Windows.Data.FilterDescriptor filterDescriptor
                        in e.OldItems.OfType<Telerik.Windows.Data.FilterDescriptor>())
                    {
                        this.RemoveFilter(filterDescriptor);
                    }
                    break;
                case NotifyCollectionChangedAction.Reset:
                    this.dds.FilterDescriptors.Clear();
                    foreach (Telerik.Windows.Data.FilterDescriptor filterDescriptor in cfd.FilterDescriptors)
                    {
                        this.AddFilter(filterDescriptor);
                    }
                    break;
            }
            ReloadData();
        }
  
        private void AddFilter(Telerik.Windows.Data.FilterDescriptor filterDescriptor)
        {            
            // Create the corresponding RIA filter based on the Telerik one.
            System.Windows.Controls.FilterDescriptor riaFilterDescriptor =
                CreateRIAFilterDescriptor(filterDescriptor);
  
            // Link them together so that we can find the RIA one when the 
            // Telerik one fires PropertyChanged, i.e. you change its operator, value, etc.
            this.filterMap[filterDescriptor] = riaFilterDescriptor;
  
            // Listen for property changes, i.e. member, operator, value, etc.
            filterDescriptor.PropertyChanged += this.OnFilterDescriptorPropertyChanged;
  
            // We will add the descriptor, once it becomes active, i.e. when its
            // value becomes something different from FilterDescriptor.UnsetValue
        }
  
        private void RemoveFilter(Telerik.Windows.Data.FilterDescriptor filterDescriptor)
        {
            // Find the corresponding RIA filter from the hashtable.
            System.Windows.Controls.FilterDescriptor riaFilterDescriptor = this.filterMap[filterDescriptor];
  
            // Delete it from the map, since it is going away.
            this.filterMap[filterDescriptor] = null;
  
            // Unhook the event listener because we will no longer need it.
            filterDescriptor.PropertyChanged -= this.OnFilterDescriptorPropertyChanged;
  
            // Finally, remove the RIA filter from the DomainDataSource.
            this.dds.FilterDescriptors.Remove(riaFilterDescriptor);
        }
  
        private void OnFilterDescriptorPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Telerik.Windows.Data.FilterDescriptor filterDescriptor = (Telerik.Windows.Data.FilterDescriptor)sender;
  
            // Find the corresponding RIA filter from the hashtable.
            System.Windows.Controls.FilterDescriptor riaFilterDescriptor = this.filterMap[filterDescriptor];
  
            switch (e.PropertyName)
            {
                case "Member":
                    riaFilterDescriptor.PropertyPath = filterDescriptor.Member;
                    break;
                case "Operator":
                    riaFilterDescriptor.Operator = CreateRIAOperator(filterDescriptor.Operator);
                    break;
                case "Value":
                    // DDS is picky about these kinds of things.
                    if (filterDescriptor.Value == null
                        && filterDescriptor.Operator != Telerik.Windows.Data.FilterOperator.IsEqualTo
                        && filterDescriptor.Operator != Telerik.Windows.Data.FilterOperator.IsNotEqualTo)
                    {
                        filterDescriptor.Value = Telerik.Windows.Data.FilterDescriptor.UnsetValue;
                    }
  
                    riaFilterDescriptor.Value = filterDescriptor.Value;
  
                    // In case this filter is being activated for the first time -- add it.
                    if (!Telerik.Windows.Data.FilterDescriptor.UnsetValue.Equals(riaFilterDescriptor.Value)
                        && !this.dds.FilterDescriptors.Contains(riaFilterDescriptor))
                    {
                        this.dds.FilterDescriptors.Add(riaFilterDescriptor);
                    }
  
                    break;
                case "IsCaseSensitive":
                    riaFilterDescriptor.IsCaseSensitive = filterDescriptor.IsCaseSensitive;
                    break;
            }
            if (riaFilterDescriptor.PropertyPath != null && riaFilterDescriptor.Operator != null && riaFilterDescriptor.Value != null)
            {
                ReloadData();
            }
        }
  
        void ReloadData()
        {
            //if (dds != null && dds.CanLoad)
            //{
            //    dds.Load();
            //}
        }
  
        private static System.Windows.Controls.FilterOperator CreateRIAOperator(Telerik.Windows.Data.FilterOperator filterOperator)
        {
            return (System.Windows.Controls.FilterOperator)Enum.Parse(typeof(System.Windows.Controls.FilterOperator), filterOperator.ToString(), true);
        }
  
        private static System.Windows.Controls.FilterDescriptorLogicalOperator CreateRIALogicalOperator(Telerik.Windows.Data.FilterCompositionLogicalOperator logicalOperator)
        {
            return (System.Windows.Controls.FilterDescriptorLogicalOperator)Enum.Parse(typeof(Telerik.Windows.Data.FilterCompositionLogicalOperator), logicalOperator.ToString(), true);
        }
  
        private static System.Windows.Controls.FilterDescriptor CreateRIAFilterDescriptor(Telerik.Windows.Data.FilterDescriptor filterDescriptor)
        {
            System.Windows.Controls.FilterDescriptor riaFilterDescriptor = new System.Windows.Controls.FilterDescriptor();
            riaFilterDescriptor.PropertyPath = filterDescriptor.Member;
            riaFilterDescriptor.Operator = CreateRIAOperator(filterDescriptor.Operator);
            riaFilterDescriptor.Value = filterDescriptor.Value;
            riaFilterDescriptor.IsCaseSensitive = filterDescriptor.IsCaseSensitive;
  
            // This is very important. Telerik filters are born with a value equal to 
            // Telerik.Windows.Data.FilterDescriptor.UnsetValue. Set this to be the
            // IgnoredValue value so that the DomainDataSource knows that such filters
            // are not yet active.
            riaFilterDescriptor.IgnoredValue = Telerik.Windows.Data.FilterDescriptor.UnsetValue;
  
            return riaFilterDescriptor;
        
    }
<local:DatagridFilter x:Name="dgFilter" >  
            <local:DatagridFilter.ItemPropertyDefinitions>
                <telerikFilter:ItemPropertyDefinition  PropertyName="ItemID" DisplayName="ItemID" PropertyType="{Binding Int32, Source={StaticResource PropertyTypes}}" />              
            </local:DatagridFilter.ItemPropertyDefinitions>
        </local:DatagridFilter>
  
        <telerikGridView:RadGridView  >        
            <telerikGridView:RadGridView.Columns>
            <telerikGridView:GridViewDataColumn Header="Item ID" DataMemberBinding="{Binding ItemID}"  />
           </telerikGridView:RadGridView.Columns>
 </telerikGridView:RadGridView  >        

1 Answer, 1 is accepted

Sort by
0
Rossen Hristov
Telerik team
answered on 06 May 2011, 07:20 AM
Hi david mcintyre,

Have you considered using RadDomainDataSource instead of the stock DomainDataSource. The benefit that you will get is that RadDataFilter will automagically integrate with RadDomainDataSource and you will not have to write any code at all. When the user filters with RadDataFilter, this will be automatically translated into a server-side filter operation. A demo of this can be seen here.

To explore the new RadDomainDataSource control in greater depth, please check itsonline examples and take a look at the following blog posts:

The difference between both controls is that RadDomainDataSource and RadDataFilter will integrate code-lessly, while if you use the MS DomainDataSource you will have to translate filter descriptors back and forth. Furthermore, the MS DomainDataSource does not support hierarchical filters.

Your best option would be to use RadDomainDataSource, which will save you a lot of time.

In case you don't want to use RadDomainDataSource for some reason or other, I will ask you to send a sample project that reproduces the behavior you ware faced with. Unfortunately, I cannot tell what is going on without being able to actually debug something.

By the way, both RadDomainDataSource and the MS DomainDataSource have a property called AutoLoad. AutoLoad will auto-load when something changes -- for example the filter descriptors. Maybe this is the prop that you are looking for.

Thanks in advance. I am looking forward to hearing from you.

Best wishes,
Ross
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Tags
DataFilter
Asked by
david mcintyre
Top achievements
Rank 1
Answers by
Rossen Hristov
Telerik team
Share this question
or