‘Google Images Style’ GridView

For one of the upcoming updates of the app I’m currently working on, the designers used a grid that looks a lot like the GridView that Google uses on it’s Images search result page.
It’s basically some sort of WrapGrid, but when selecting an item, the Grid expands and the selected item is shown on the next row spanning the entire width of the grid. One gif says more than a thousand words (and it is the final result of my custom control):
I was suprised about how easy it was to build this control in UWP. First I was thinking about using things like UI Composition and stuff, but then I realised it also COULD be possible by using the standard GridView control (together with the VariableSizedWrapGrid).
The setup of this control is quite simple and straightforward. There is, however, still lots of room for improvements. But more on this later in this blogpost.


Warning: although this control isn’t that complex, explaining how everything works together in a blogpost isn’t that easy (but I’m going to give it a try). So if you would really want to understand how this control works, I’d recommend to download the source code and walk through it yourself. 🙂


Basically, the control is just a GridView with a VariableSizedWrapGrid as ItemsPanel. I define that the Items in this GridView are clickable and I register an EventHandler for both the ItemClicked and SizeChangedEvent. In the ItemClick eventhandler is where most of the control’s logic is situated, I’ll dive into this in just a minute. In the SizeChanged eventhandler, I’m going to close the detail view if it were open, so I don’t have to recalculate the possition and size of the detail view.
The Bindings you see here are Bindings to DependencyProperty Properties that I’ve put on my ExpandableDetailGridView control.

Let’s take a look at the code-behind

There are some Dependency Properties that I’ve defined. The purpose of most of these properties should be quite clear. However, I would like to point out some of them.
SelectedItem is, as it name suggests, the item that is selected in the grid.
DetailItem is the data that is shown in the DetailView. This doesn’t have to be of the same type as the objects in the Items list or as the SelectedItem.
IsOverviewDataSameAsDetailData when this property is set to ‘true’, the control will automatically set the DetailItem to the same value as the SelectedItem. However, in some cases you might want to show other data (more details) on the DetailView. In these cases you can set the IsOverviewDataSameAsDetailData flag to ‘false’ and set the DetailItem yourself when, for example, the SelectedItem changes (you can find an example of both in the Demo project that is included in the sources).
Most of the code of the control can be found inside the ItemClick eventhandler:

In this method we do some basic calculations on where to put the DetailView inside the GridView, that is on the row below the clicked item.

You’ll see that there is this odd thing ‘if (Animate) await Task.Delay(55);’… Well, I noticed that if I remove the existing DetailItem from the Grid, give the UI some processing time, that there is this nice animation of the DetailView being removed and then re-added to the GridView.

We also create a DetailGridItem, which is a wrapper around our DetailItem. This DetailGridItem object looks like this:

The DataContext of this DetailGridItem will be set to the same value as the DetailItem Dependecy Property. We do this as follows when the DetailItem changes on the ExpandableDetailGridView:

In this object we also hold the Template that should be used on the selected DetailItem and a reference to our ExpandableDetailGridView. On the Template of the DetailGridItem, we can define a button that will hide the DetailView when we click on it.

Oh, and one more thing… You see that ‘arrow’ below the SelectedItem in the Grid? I’ve done this by giving the GridViewItems in the Grid a custom style, like this:

And that’s all there is to it!
We can now easily use this control as follows:


Final thoughts

Yes, I know, this Control is far from finished. It works but there are some things that need to be improved like for example:
* setting an ObservableCollection as Items property on the ExpandableDetailGridView will not work yet as expected as I currently don’t listen to the CollectionChanged events
* setting the SelectedIndex/SelectedItem on the ExpandableDetailGridView will also not work
* the events on the ExpandableDetailGridView should be improved
* …
Never the less, I think for basic scenarios this control works. Below you’ll find a link to the GitHub repo with all the source code and I’ll try to improve the control over time.
If you would have any remarks, questions or suggestions, please don’t  hesitate to drop a commend below!