(Composite)FilterDescriptor and Binding

8 posts, 0 answers
  1. Espen
    Espen avatar
    16 posts
    Member since:
    Sep 2011

    Posted 24 Jun 2011 Link to this post

    So I'm trying to develop a proper MVVM solution with RadGridView and some FilterDescriptors. I've read on forums in some old posts that FilterDescriptor don't support binding, but you were supposed to add it...and looking at it now, it indeed looks like FilterDescriptor is a DependencyObject (I'm running version 2011.1.419.1040). So here's what I tried:

    <telerik:RadGridView Grid.Row="2" x:Name="BudgetGrid" AutoGenerateColumns="False"
                                     ShowGroupPanel="False"
                                     Background="{StaticResource LightGreyBackground}"
                                     ItemsSource="{Binding Posts}"
                                     RowDetailsVisibilityMode="Collapsed"
                                     RowIndicatorVisibility="Collapsed"
                                     CanUserDeleteRows="False"
                                     CanUserInsertRows="False"
                                     CanUserSelect="True"
                                     SelectedItem="{Binding DataContext.SelectedPost,Mode=TwoWay, ElementName=LayoutRoot}"
                                     DataContext="{Binding Budget}" ShowColumnFooters="True"
                                     >
                <telerik:RadGridView.FilterDescriptors>
                    <telerik:FilterDescriptor IsCaseSensitive="False"
                                              Member="Name"
                                              Operator="Contains"
                                              Value="Upd"/>
                </telerik:RadGridView.FilterDescriptors>
    </telerik:RadGridView>

    This does actually work, but isn't very dynamic (just showing snippets of the code here and there are columns in the grid). Back to the drawingboard.

    <TextBox x:Name="SearchTermTextBox" Grid.Column="0" Width="150" VerticalAlignment="Center">
           <i:Interaction.Behaviors>
                  <behaviors:UpdateOnTextChangedBehavior/>
           </i:Interaction.Behaviors>
    </TextBox>
    <telerik:RadGridView Grid.Row="2" x:Name="BudgetGrid" AutoGenerateColumns="False"
                                     ShowGroupPanel="False"
                                     Background="{StaticResource LightGreyBackground}"
                                     ItemsSource="{Binding Posts}"
                                     RowDetailsVisibilityMode="Collapsed"
                                     RowIndicatorVisibility="Collapsed"
                                     CanUserDeleteRows="False"
                                     CanUserInsertRows="False"
                                     CanUserSelect="True"
                                     SelectedItem="{Binding DataContext.SelectedPost,Mode=TwoWay, ElementName=LayoutRoot}"
                                     DataContext="{Binding Budget}" ShowColumnFooters="True"
                                     >
                <telerik:RadGridView.FilterDescriptors>
                    <telerik:FilterDescriptor IsCaseSensitive="False"
                                              Member="Name"
                                              Operator="Contains"
                                              Value="{Binding ElementName=SearchTermTextBox,Path=Text}"/>
                </telerik:RadGridView.FilterDescriptors>
    </telerik:RadGridView>

    This doesn't work at all. It seems like the FilterDescriptor can't locate the SearchTermTextBox. If that is the case, what's the point of adding support for binding on a FilterDescriptor? Seems kind of odd to me. I've tried a few other different approaches with no luck as well. Looking at the demo (http://demos.telerik.com/silverlight/#GridView/Search) doesn't help either. I'm not going to add the GridView in my viewmodel as suggested there.

    Bottom line...is there a proper MVVM way to use this functionality?
  2. Dimitrina
    Admin
    Dimitrina avatar
    3769 posts

    Posted 28 Jun 2011 Link to this post

    Hi Espen Berglund,

     Binding with the ElementName in the Silverlight GridView is not the best way to go. ElementName uses the logical tree to find the element in the element name binding.  Parts of the telerik grid (and the sl data grid), do not participate in this part of the tree, or they have not been created yet at the time of binding (since most of the grid is dynamically generated), so it cannot be resolved.

    Generally the better approach is to bind a Dependency Object to a property in your ViewModel. This is MVVM friendly.

    I have created a sample project where a TextBox and FilterDescriptor are bound to the same property:

    <telerik:RadGridView.FilterDescriptors>
     <telerik:FilterDescriptor IsCaseSensitive="False"
                Member="Name"
            Operator="Contains"
        Value="{Binding Source={StaticResource MyViewModel}, Path=SearchString}" />
    </telerik:RadGridView.FilterDescriptors>

    May you please review the project and share if this is working for you?

    All the best,
    Didie
    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. Bahri Gungor
    Bahri Gungor avatar
    11 posts
    Member since:
    Jun 2005

    Posted 29 Aug 2011 Link to this post

    Didie,

    I am also trying this technique, but the value I am bound to is a Nullable<int> (aka int?):

    <telerik:RadGridView ItemsSource="{Binding Orders}" RowStyle="{StaticResource rowStyle}">
        <telerik:RadGridView.FilterDescriptors>
            <telerik:FilterDescriptor Member="CustomerID" Value="{Binding SelectedCustomerID, Mode=OneWay}" Operator="IsEqualTo"/>
        </telerik:RadGridView.FilterDescriptors>
    </telerik:RadGridView>

    Problem 1: When it binds it is throwing an argument exception (Argument types do not match) in FilterDescriptorExpressionBuilder.CreateConstantExpression at "return Expression.Constant(null, targetType);"

    Problem 2:  I want the filter to be inactive if the SelectedCustomerID is actually null.  I have no orders where the customerID is null.  How would I enable this in XAML?  I saw something relating to UnsetValue, but it was confusing that it would be a static value on the FilterDescriptor class, as wouldn't each bound filter be for different column values?

    My bound viewmodel looks like this:

    public class ActiveOrdersViewModel : ViewModelBase
     {
            private int? _selectedCustomerID;
     
            public int? SelectedCustomerID
            {
                get { return _selectedCustomerID; }
                set
                {
                    _selectedCustomerID = value;
                     
                    NotifyPropertyChanged("SelectedCustomerID");
                    NotifyPropertyChanged("Orders");
                }
            }
     
            private ObservableCollection<OrderItemViewModel> _orders = null;
     
            public ObservableCollection<OrderItemViewModel> Orders
            {
                get { return _orders; }
                set { _orders = value; }
            }
    }

    Please help...
  4. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 02 Sep 2011 Link to this post

    Hello Bahri Gungor,

    Please set the Source property in the Binding of the Value - just as illustrated in the code-snippet Didie provided. Do you get the same exception ?
    As for the second issue, depending on your particular requirements, you may indeed try to set the Value to FilterDescriptor.UnsetValue. This will be applied only for the FilterDescriptor for the corresponding Member.

     

    Best wishes,
    Maya
    the Telerik team

    Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

  5. Bahri Gungor
    Bahri Gungor avatar
    11 posts
    Member since:
    Jun 2005

    Posted 02 Sep 2011 Link to this post

    Maya, 

    Thank you for your reply. 

    I changed the source binding to the following, which should now resolve correctly to my ViewModel (thank you).

    <telerik:FilterDescriptor Member="CustomerID" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl}},Path=SelectedCustomerID, Mode=OneWay}" Operator="IsEqualTo"/>

    I still got the exception that I explained before until I changed the CustomerID value in the OrderItemViewModel (the list item type) to Nullable<int>.  Apparently the search logic you use can't correctly handle the conversion of a Nullable type to it's value type for comparison.  It would be great if you could add that functionality.  It would be great if you could add a switch to turn off the filter for a nullable comparison type as to whether it should be the UnsetValue for that column.

    I still have issues, I believe because my CustomerID is set to AutoGenerateFilter = true, but AutoGenerateColumn = false.  There are no records showing no matter what the filter value is.
    Unfortunately I am under the gun to finish a release right now.  I'll have to tackle this later this fall.

    Thanks for the help!

  6. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 03 Sep 2011 Link to this post

    Hi Bahri Gungor,

    If you find time to prepare a sample project simulating your scenario (or update the one attached here), we will debug it locally and try to provide solution for the problems you struggle with.

     

    Best wishes,
    Maya
    the Telerik team

    Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

  7. Mathi Sekaran
    Mathi Sekaran avatar
    4 posts
    Member since:
    Jul 2009

    Posted 21 Dec 2011 Link to this post

    I've been trying to get this working using SL5's relative source binding however, when debugging the binding, my breakpoint is only being hit when the Binding.Source property is used, it doesn't get hit when i specify a Binding.RelativeSource.

    For testing I'm using a similar line of xaml as Bahri was:

    <telerik:FilterDescriptor IsCaseSensitive="false"
                      Member="description" Operator="Contains"
                      Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType=UserControl},Path=SearchText, Mode=OneWay}"/>

    The structure of the code base means I can't use a static resource; my views and VMs are connected together by a managing component.
  8. Nuno
    Nuno avatar
    2 posts
    Member since:
    Oct 2011

    Posted 21 Dec 2011 Link to this post

    Hello,

    I have a problem in my GradView that is bonded to a QueryableDomainServiceCollectionView in my ModelView. The problem is that it does not filters correctly when i create a filter from the filter column. I notice that it filters some data from that column para not all. The curios is that when i sort that parameter directly in the data source (from the domain data) it works fine.
    here is the code from my RadGridView:

    <telerik:RadGridView Name="RadGridView1" 
                                                                     AlternationCount="2" 
                                                                     ItemsSource="{Binding ReportData, Mode=TwoWay}" 
                                                                     IsBusy="{Binding Path=ReportData.IsBusy}" 

                                                                     EnableColumnVirtualization="True"                                                                  
                                                                     EnableRowVirtualization="True"
                                                                     IsReadOnly="True"                                                                                                                      
                                                                     Width="900"
                                                                     Height="400"
                                                                     RowIndicatorVisibility="Collapsed">


                                                    <telerik:RadGridView.AlternateRowBackground>
                                                        <SolidColorBrush Color="#25F29500"></SolidColorBrush>
                                                    </telerik:RadGridView.AlternateRowBackground>
                                                    <telerik:RadContextMenu.ContextMenu>
                                                        <telerik:RadContextMenu x:Name="ContextMenu" 
                                                                                ItemClick="ContextMenuClick" 
                                                                                Opened="RadContextMenu_Opened">
                                                            <telerik:RadMenuItem Header="Editar" />
                                                            <telerik:RadMenuItem IsSeparator="True" />
                                                            <telerik:RadMenuItem Header="Apagar" />
                                                        </telerik:RadContextMenu>
                                                    </telerik:RadContextMenu.ContextMenu>                                                
                                                </telerik:RadGridView>

    here is the code from the MV:

    public ReportViewModel()
            {
               
                    EntityQuery<cti2_Report_PackageCountersWithCategories> query = Cti2DomainClient.GetReport_PackageCountersWithCategoriesQuery();
                    
                    ReportData = new QueryableDomainServiceCollectionView<cti2_Report_PackageCountersWithCategories>(Cti2DomainClient, query);
                    ReportData.PageSize = PageSize;
                    ReportData.AutoLoad = true;
    }

    public partial class Cti2EntityService
        {

    Here is the code from my DomainService in the host project:

            public IQueryable<cti2_Report_PackageCountersWithCategories> GetReport_PackageCountersWithCategories()
            {
                IQueryable<cti2_Report_PackageCountersWithCategories> query =
                    this.ObjectContext.cti2_Report_PackageCountersWithCategories.OrderBy(c => c.idPackage);
    return query;
    }

Back to Top