提高WPF中的绑定性能?

时间:2010-07-30 21:24:32

标签: c# wpf performance data-binding collections

我意识到这个问题可以归结为“我的代码为什么这么慢?”但我希望能从中得到更多。让我解释一下我的代码。

我有一个实现INotifyPropertyChanged的类来进行绑定,该类看起来类似于:

  public class Employee : INotifyPropertyChanged 
    { 
        string m_strName = "";
        string m_strPicturePath = "";
        public event PropertyChangedEventHandler PropertyChanged;

        public string Picture
        {
            get { return this.m_strPicturePath; }
            set { this.m_strPicturePath = value; 
            NotifyPropertyChanged("Picture"); }
        }

        public string Name
        {
            get { return this.m_strName; }
            set { this.m_strName = value;
            NotifyPropertyChanged("Name");
            }
        }

        private void NotifyPropertyChanged(String pPropName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(pPropName));
            }
        }
    }

在我的XAML中,我创建了一个绑定到该对象的DataTemplate:

 <DataTemplate x:Key="EmployeeTemplate">
        <Border Height="45" CornerRadius="0" BorderBrush="Gray" BorderThickness="0" Background="Transparent" x:Name="bordItem">
            <Grid Width="Auto">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Path=Name}" VerticalAlignment="Center" Padding="10" HorizontalAlignment="Stretch" FontWeight="Bold" FontSize="20"/>
                <Image Grid.Column="1" Source="{Binding Path=Picture}"></Image>
            </Grid>
        </Border>
    </DataTemplate>

然后将此模板放在ListBox上:

<ListBox x:Name="lstEmployees" ItemTemplate="{DynamicResource EmployeeTemplate}" VirtualizingStackPanel.VirtualizationMode="Recycling" VirtualizingStackPanel.IsVirtualizing="True"></ListBox>

所以在代码中它被设置为:

lstEmployees.ItemsSource = this.m_Employees;

“m_Employees”列表在应用程序启动时从数据库中获得水分,然后在此之后我设置上面的代码行。 ListBox位于TabControl上。

现在,我的实际问题:我的“m_Employees”列表从数据库中返回了大约500多名员工,因此集合稍大。当应用程序首次启动时,我在WPF 中获得性能提升,并且有人导航到该选项卡上,其中包含ListBox。用户界面冻结大约3秒钟,但只有在应用程序首次启动时才会冻结 - 之后就可以了。

这可能是因为:

  • 代码必须点击硬盘才能找到每个员工的形象?
  • 我正在虚拟化虚拟化?
  • 修改
  • WPF正在使用我的DataTemplate进行渲染一次,只有当有人导航到那个TabControl时,才会突然尝试绘制500多个员工项目?如果是这样,有没有办法在WPF中“预加载”ListView?

任何其他改善上述建议都会受到赞赏。感谢您提前阅读和提出任何建议。

-R

2 个答案:

答案 0 :(得分:8)

  1. 用公共包装m_Employees 财产(雇员)
  2. 不要像你那样在代码中设置ItemsSource,而是使用Binding设置它并将IsAsync设置为 真。
  3.   

    ItemsSource =“{Binding Empolyess, IsAsync = True }”

    您也可以在代码中指定Binding。

    希望这有帮助。

答案 1 :(得分:0)

你的查询的性能肯定是可疑的。如果您希望它的性能更好,您可以执行任意数量的延迟初始化技术,以使其运行得更快。

最简单的选择是以空枚举开始,并且只在以后填充它。

显而易见的方法是添加“查询”或“刷新”按钮,并在用户点击它时冻结应用。

另一个简单的选择是对后台任务/线程进行排队以进行刷新。

如果您更关注一致性的perf / super-responsive UI,那么您应该尝试进行更细粒度的查询。

我不确定WPF是否处理项目的虚拟化(只有在每个项目进入视图时才从枚举中提取),但如果确实如此,则可以执行分页/收益返回以提供ItemsSource。

如果WPF只是立即获取整个枚举,如果您可以确定哪些项目在视图中,您仍然可以执行更小的延迟/分页。只需使用“zombie”项目填充对象,当它们进入视图时,执行查询,并更新单个项目的属性。