ItemsSource to QueryableCollectionView bound to RadGridView during grouping

12 posts, 1 answers
  1. Patrick
    Patrick avatar
    50 posts
    Member since:
    Jan 2013

    Posted 14 Dec 2016 Link to this post

    Hello,

    We have a TileView and GridView on the UI side by side bound to the same collection inside a ViewModel using a QueryableCollectionView, which is sourced by an ObservableCollection<MyGridData>. When the GridView is filtered, sorted, items are added/removed, etc the TileView works and updates perfectly. Our only issue is when the GridView is grouped, the underlying class of the inside the QueryableCollectionView changes from MyGridData to a new Grouping Class, which the TileView templates do not know how to render. This causes the count of TileView items to match the number of groupings, and the TileView icons themselves to be blank.

    How do you recommend binding these two controls to allow the GridView to group and still hand back MyGridData in the grouped order?

    Thank you,

    Patrick

  2. Patrick
    Patrick avatar
    50 posts
    Member since:
    Jan 2013

    Posted 16 Dec 2016 in reply to Patrick Link to this post

    Only 1 view. Anyone? Bueller?
  3. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2955 posts

    Posted 19 Dec 2016 Link to this post

    Hi Patrick,

    Grouping in RadTileView is not supported out of the box. You can vote for the following feature request.

    TileView: Add grouping support.

    What we can suggest you is implementing custom grouping. For example you need normal ContentTemplate for RadTileView in non-grouped state and custom ContentTemplate (containing for example ListBox) for grouped RadTileView. Switching these templates and ItemsSource of the RadTileView could be done in the GridView grouping events.


    Regards,
    Petar Mladenov
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  4. Patrick
    Patrick avatar
    50 posts
    Member since:
    Jan 2013

    Posted 19 Dec 2016 in reply to Petar Mladenov Link to this post

    Hello Petar,

    We would prefer the TileView look exactly the same and essentially ignore the grouping but maintain the item order. This would be more of a change to the source collection. We have this in other parts of our UI where the GridView and the TileView have two different source collections that represent the same list of items. Keeping the two collections in sync without issue can be a challenge. This is where the QueryableCollectionView bound to the GridView was *almost* exactly what we needed, with the exception of grouping. We were inquiring if you had another method to essentially flat list the items for the TileView when grouping.

    Right now I am looking into creating a derived class of QueryableCollectionView which has a property called 'GrouplessSource', but again this is maintaining a separate list of items and is far from ideal.

    Do you have any other suggestions?

    Thank you Petar.

  5. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2955 posts

    Posted 22 Dec 2016 Link to this post

    Hello Patrick,

    We would suggest using a converter for the ItemsSource binding of the RadTileView. If groups are passed in the converter and they provide child collections of (flat) item, then create the flat collection you need in the converter.  However, this is only shoot in the dark. We tried to replicate your scenario - GridView and TileView both bound to QueryableCollectionView. Please check out our test project and notice that when you group by Name column, the TileView does not change. Can you edit the project to replicate your scenario ?

    Regards,
    Petar Mladenov
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  6. Patrick
    Patrick avatar
    50 posts
    Member since:
    Jan 2013

    Posted 22 Dec 2016 in reply to Petar Mladenov Link to this post

    Hello again Petar,

    I could not reproduce the issue in your attached app. After tweaking a few things in both our SL app, and your WPF app I decided to make a SL app with exactly the same code as your test app and it reproduced our issue immediately. I cleared out DisplayMemberPath to call ToString() on the underlying class. It looks like they are different in SL vs WPF. The WPF behavior is what we are looking for, although the SL behavior is more what I would expect when the grouping is added to a QueryableCollectionView. Which one is "correct"?

    If you'd like I'd be happy to zip up both projects to send them, but I can't attach files in this forum.

    Thanks for your time on this.

     

  7. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2955 posts

    Posted 27 Dec 2016 Link to this post

    Hello Patrick,

    There are some implementation differences in Silverlight / WPF regarding grouping with QueryableCollectionView. However, your main goal is to ignore the grouping in RadTileView, right. We want to suggest the following - bind the ItemsSource of the RadTileVeiw to the SourceCollection property of the QCV:

    QueryableCollectionView view = new QueryableCollectionView(Club.GetClubs());
             this.grid.ItemsSource = view;
             this.DataContext = view;

    <telerik:RadTileView DisplayMemberPath="Name" x:Name="tileView" Grid.Row="2"
                               ItemsSource="{Binding SourceCollection}">

    This way the TileView will remain with tielviewitems number equal to the items in the source collection of the QCV and will ignore the grouping. Please find this realized in the attached SL project. Additionally, please excuse us for misleading you with WPF project, instead of SIlverlight's int he previous reply.

    Regards,
    Petar Mladenov
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  8. Patrick
    Patrick avatar
    50 posts
    Member since:
    Jan 2013

    Posted 28 Dec 2016 in reply to Petar Mladenov Link to this post

    Hello Petar,

    I'm afraid that won't work for us either, the SourceCollection does not update with sorting and filtering as binding directly to the QueryableCollectionView does. This is the expected behavior in the rest of our UI, the TileView is a representation of the GridView items. As stated previously it's almost perfect, with great performance without having to maintain 2 sources, except we want to flat list when grouping, which it seems WPF does and SL does not.

    I tried a converter on the TileView itemsource as previously suggested, but this is only called once on instantiation. This does not help when a grouping is added, the converter is not called again. If it was, we could easily loop though recursively find all the groups within groups and hand back the flat listed items ourselves.

    Any other suggestions?

    Thank you,

    Patrick

  9. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2955 posts

    Posted 30 Dec 2016 Link to this post

    Hello Patrick,

    We understand binding is not updated when grouping is performed. Is using Grouping events still an option, use the event and manually re-set the ItemsSource of the RadTileView on group / ungroup ?

    RadGridView Grouping Events

    Regards,
    Petar Mladenov
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  10. Patrick
    Patrick avatar
    50 posts
    Member since:
    Jan 2013

    Posted 30 Dec 2016 in reply to Petar Mladenov Link to this post

    Hello Petar,

    I was able to get what appears to be the desired behavior with a mixture of things. The RadTileView has a converter on the ItemsSource, the grid has a 'Grouped' event handler (only for grouping removes), and the QueryableCollectionView has an event handler on changes (this keeps up with changes to grid sorts/filters on the grid while grouping)

    public class QCVGroupFlatListConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var source = value as QueryableCollectionView;
            if (source != null && source.IsGrouped)
            {
                var ungrouped = new List<object>();
                for (int i = 0; i < source.Count; i++)
                {
                    var d = source[i] as object;
                    if (d != null)
                    {
                        ungrouped.Add(d);
                    }
                }
     
                return ungrouped;
            }
     
            return value;
        }
     
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

     

    01.public partial class MainPage : UserControl, INotifyPropertyChanged
    02.{
    03.    #region INotifyPropertyChanged Members
    04. 
    05.    protected void OnPropertyChanged(string property)
    06.    {
    07.        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    08.    }
    09. 
    10.    public event PropertyChangedEventHandler PropertyChanged;
    11. 
    12.    #endregion INotifyPropertyChanged Members
    13. 
    14.    private QueryableCollectionView _MyList;
    15. 
    16.    public QueryableCollectionView MyList
    17.    {
    18.        get { return _MyList; }
    19.        set
    20.        {
    21.            if (_MyList == value)
    22.                return;
    23. 
    24.            _MyList = value;
    25.            OnPropertyChanged(nameof(MyList));
    26.        }
    27.    }
    28. 
    29.    public MainPage()
    30.    {
    31.        MyList = new QueryableCollectionView(Club.GetClubs());
    32.        MyList.CollectionChanged += MyList_CollectionChanged;
    33.        DataContext = this;
    34. 
    35.        InitializeComponent();
    36.    }
    37. 
    38.    private void MyList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    39.    {
    40.        if (((QueryableCollectionView)sender).IsGrouped)
    41.            OnPropertyChanged(nameof(MyList));
    42.    }
    43. 
    44.    private void RadGridView_Grouped(object sender, Telerik.Windows.Controls.GridViewGroupedEventArgs e)
    45.    {
    46.        if (e.Action == Telerik.Windows.Controls.GroupingEventAction.Remove)
    47.            OnPropertyChanged(nameof(MyList));
    48.    }
    49.}

     

    I believe this is causing the grid to reevaluate it's own ItemsSource on group changes since it is also bound to 'MyList', but I didn't notice any performance issues, even with 1000+ items. Perhaps the grid is ignoring the update since no real change is happening?

     

    Worth noting is how looping through a QueryableCollectionView behaves in SL:

    foreach() and for() on QueryableCollectionView while grouping return two completely different things
    for() accessed with an index, as in source[i], returns the underlying object whereas
    foreach() returns AggregateFunctionsGroup, which could be nested with more groups
    ex: [Group: Key=Arsenal; ItemCount=2; HasSubgroups=False; ParentGroup=null]

    Thank you,

    Patrick

  11. Answer
    Petar Mladenov
    Admin
    Petar Mladenov avatar
    2955 posts

    Posted 04 Jan Link to this post

    Hi Patrick,

    Here are our answers:

    Perhaps the grid is ignoring the update since no real change is happening?

    Yes the grid find there is no change of the ItemsSource object.

    Worth noting is how looping through a QueryableCollectionView behaves in SL:

    When you *for* you use the indexator element[i], and when you use *foreach* you use the enumerator returned by the GetEnumerator method so the mentioned difference is expected.

    We also wanted to suggest another solution you can try - bind the ItemsSource of the RadTileView to the GridView's Items property:

    <telerik:RadTileView DisplayMemberPath="Name" x:Name="tileView" Grid.Row="2" ItemsSource="{Binding Items, ElementName=grid}">




    Regards,
    Petar Mladenov
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  12. Patrick
    Patrick avatar
    50 posts
    Member since:
    Jan 2013

    Posted 09 Jan in reply to Petar Mladenov Link to this post

    This single line is what we needed.

    ItemsSource="{Binding Items, ElementName=grid}"

    Thank you.

Back to Top