ItemPropertyDefs in unbound mode

2 posts, 0 answers
  1. david mcintyre
    david mcintyre avatar
    31 posts
    Member since:
    Mar 2010

    Posted 05 May 2011 Link to this post

    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  >        
  2. Rossen Hristov
    Admin
    Rossen Hristov avatar
    2478 posts

    Posted 06 May 2011 Link to this post

    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
  3. DevCraft banner
Back to Top