【问题标题】:Performance degredation with custom ListBox ControlTemplate使用自定义 ListBox ControlTemplate 降低性能
【发布时间】:2012-10-01 15:56:45
【问题描述】:

对源自ListBox 的自定义控件使用模板会导致过滤ItemSource 变慢。过滤是在控件绑定到的ItemSource 的get 中完成的。使用普通的ListBox 时不会出现此问题,那么为什么自定义ListBox 会有所不同?

过滤:

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);
    }
}  

使用控件:

<con:FilterListBox Grid.Row="1"
                   ItemsSource="{Binding Libraries}"
                   SelectedItem="{Binding SelectedLibrary}"
                   ItemTemplate="{StaticResource  
                                  LibraryItemTemplate}"                           
                   SearchString="{Binding LibrarySearchString, Mode=TwoWay}"
                   IsSearching="False"
                   Margin="4"/>

控制模板:

<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>

感谢您的帮助。

【问题讨论】:

    标签: wpf mvvm listbox controltemplate


    【解决方案1】:

    FilterListBox 的缓慢行为可能伴随着虚拟化问题。您将 ListBox 的 ItemsHost 替换为简单的 StackPanel。默认情况下,ListBox 使用VirtualizingStackPanel,它会尽可能虚拟化项目。请参阅默认列表框模板作为参考。如果您有一个简单的 StackPanel 作为 ItemsPresenter,则 ListBox 必须在您的过滤器更改时重新呈现每个项目。根据项目的数量,这可能会导致您的行为缓慢。尝试改用默认的 itemshost。您还应该知道,虚拟化仅适用于“简单”项目(基本上每个项目的高度相同)。

    【讨论】:

    • 非常感谢您的回答,我明天再试一试。我的列表中有大约 1000 项,是的,如果我减少了这个,那么性能问题就会消失,所以我相信你是对的!
    • 应该注意,虚拟化您的 ListBox 可能不仅仅是使用 VirtualizingStackPanel。更多详情请见this answer
    • +1 是的,我忘了提。您必须设置更多属性才能将其虚拟化。 Rachel 链接中的答案提供了所需的一切。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多