Recently we received several requests for an example, demonstrating how to put a virtualized GridView in a ComboBox popup. The best way to do this in my opinion is to replace the ItemsPresenter of the ComboBox with a GridView. There is some plumbing that has to be done, but I managed to separate it in two attached behaviors. The original idea is described in my blog post for TreeView in ComboBox which I recently updated with the latest control template of RadComboBox for Silverlight. The principle is exactly the same with RadGridView and it should work with very minor adjustments with any GridView, including the one from the Silverlight Toolkit:

<!-- NonEditableComboBoxTemplate --> <ControlTemplate x:Key="NonEditableComboBox" TargetType="input:RadComboBox"> <Grid Name="MainGrid"> <ToggleButton x:Name="DropDownButton" /> <ContentPresenter /> <Popup x:Name="PART_Popup"> <gridView:RadGridView local:GridViewExtensions.EnableSelectionChangedRoutedEvent="True" RowIndicatorVisibility="Collapsed" CanUserReorderColumns="False" ShowGroupPanel="False" CanUserSortColumns="False" ItemsSource="{TemplateBinding ItemsSource}" SelectedItem="{TemplateBinding SelectedItem}" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding MinDropDownWidth}" /> </Popup> <Rectangle x:Name="DisabledVisual" /> </Grid> </ControlTemplate>


There is a catch, though - we should remove the ComboBox’s ScrollViewer from the template, because it will break the GridView UI virtualization. I will try explain why: the UI virtualization lets the control render only its currently visible items and when you scroll, the UI elements that disappear from the view port are discarded and new UI elements are created for the newly displayed items, or in some cases the disappearing UI elements are reused (this technique is called container recycling). This means that the count of the UI elements that is rendered depends on the height of the control – when the control is taller, it renders more items, when it is shorter, it renders fewer items. The ScrollViewer measures the controls that are inside it with positive infinity, which is virtually the same as when you set Height=double.PositiveInfinity. This means that if we put any virtualized control in a ScrollViewer, it will render all of its items.

Other problem that I needed to workaround is the selection synchronization. Since RadGridView for Silverlight exposes a plain CLR event (not a routed event), that is raised when the control selection changes, I created a simple attached behavior that raises a custom routed event when the CLR event of RadGridView is raised. This helps me to “catch” the selection change event “outside” the RadComboBox control template and sync the ComboBox selection with the inner GridView selection.

The complete source code of the example can be downloaded from here:

Related Posts


Comments are disabled in preview mode.