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
11 Answers, 1 is accepted
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
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.
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
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.
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
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
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
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
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
This single line is what we needed.
ItemsSource="{Binding Items, ElementName=grid}"
Thank you.