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

(Composite)FilterDescriptor and Binding

8 Answers 798 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Espen
Top achievements
Rank 1
Espen asked on 24 Jun 2011, 01:57 PM
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?

8 Answers, 1 is accepted

Sort by
0
Dimitrina
Telerik team
answered on 28 Jun 2011, 08:32 AM
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
0
Bahri Gungor
Top achievements
Rank 1
answered on 29 Aug 2011, 04:53 PM
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...
0
Maya
Telerik team
answered on 02 Sep 2011, 08:23 AM
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 >>

0
Bahri Gungor
Top achievements
Rank 1
answered on 02 Sep 2011, 05:11 PM
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!

0
Maya
Telerik team
answered on 03 Sep 2011, 02:03 PM
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 >>

0
Mathi Sekaran
Top achievements
Rank 1
answered on 21 Dec 2011, 01:10 PM
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.
0
Nuno
Top achievements
Rank 2
answered on 21 Dec 2011, 05:53 PM
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;
}

0
srinivasan
Top achievements
Rank 1
answered on 11 Mar 2020, 05:14 PM

ok..I found the work around for using staticresource in MVVM.

Basically staticresource object is initialized when view is initialized. So store the instance of the object in the static field of that class, and then access that instance of the object from viewmodel and then change the value.

public class SearchData : BindableBase
{
    private static SearchData instance = null;
    private string _searchString;
 
    public string SearchString { get => _searchString; set => SetProperty(ref _searchString, value); }
 
    public SearchData()
    {
        if (instance == null)
            instance = this;
    }
    public static SearchData GetInstance()
    {
        return instance;
    }
}

 

In the view do following

i
 
<UserControl.Resources>
    <vm:SearchData x:Key="DataSource"/>
</UserControl.Resources>
        <telerik:RadGridView.FilterDescriptors>
            <telerik:FilterDescriptor IsCaseSensitive="False" Member="Name" Operator="Contains"
                                      Value="{Binding Path=SearchString, Source={StaticResource DataSource}}"/>
        </telerik:RadGridView.FilterDescriptors>

In the viewmodel do the following

SearchData SearchDataInstance;
 
private void OnSearch(string vmSearchString)
{
                    if (SearchDataInstance == null) SearchDataInstance = SearchData.GetInstance();
                    SearchDataInstance.SearchString = vmSearchString;
}

Tags
GridView
Asked by
Espen
Top achievements
Rank 1
Answers by
Dimitrina
Telerik team
Bahri Gungor
Top achievements
Rank 1
Maya
Telerik team
Mathi Sekaran
Top achievements
Rank 1
Nuno
Top achievements
Rank 2
srinivasan
Top achievements
Rank 1
Share this question
or