Reputation: 828
Using a template for a custom control deriving from ListBox
causes filtering of ItemSource
to become slow. The filtering is done in the get of the ItemSource
that the control is bound to. This problem is not present when a normal ListBox
is used, so why should it be any different for a custom ListBox
?
Filtering:
public IEnumerable<LibraryViewModel> Libraries {
get {
if (!string.IsNullOrEmpty(this.LibrarySearchString))
return _libraries.Where(lib => IsLibraryMatch(lib, this.LibrarySearchString));
else
return _libraries.OrderBy(lib => !lib.IsFavourite);
}
}
Using the control:
<con:FilterListBox Grid.Row="1"
ItemsSource="{Binding Libraries}"
SelectedItem="{Binding SelectedLibrary}"
ItemTemplate="{StaticResource
LibraryItemTemplate}"
SearchString="{Binding LibrarySearchString, Mode=TwoWay}"
IsSearching="False"
Margin="4"/>
The control template:
<Style x:Key="{x:Type con:FilterListBox}" TargetType="{x:Type con:FilterListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type con:FilterListBox}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<TextBlock Text="Search"
VerticalAlignment="Center"/>
<TextBox Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=SearchString,
UpdateSourceTrigger=PropertyChanged}"
Margin="4,0,0,0"/>
</DockPanel>
<ScrollViewer Grid.Row="1" CanContentScroll="True">
<StackPanel IsItemsHost="True"
HorizontalAlignment="Stretch"/>
</ScrollViewer>
<TextBlock Grid.Row="1"
Text="Searching..."
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=IsSearching,
Converter={StaticResource CollapsedIfFalseConverter}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thanks for any help.
Upvotes: 0
Views: 879
Reputation: 1849
The slow behavior of your FilterListBox
may come with an Virtualization issue. You replaced the ItemsHost of the ListBox
with a simple StackPanel
. By default, the ListBox uses a VirtualizingStackPanel
, which virtualizes the Items whenever possible. See the default ListBox Template as a reference. If you have a simple StackPanel as ItemsPresenter, the ListBox has to re-render every item when your filter changes. Depending on the number of items, this can cause your slow behavior. Try to use the default itemshost instead. You should also know, that virtualization is only possible with 'simple' items (same Height for every item basically).
Upvotes: 4