Wpf 渲染模板性能
我创建了一个类似propertyGrid的。 我使用了一个使用viewmodel对象的项控件。 VM对象具有要显示的属性及其相关的DataTemplates。 一切都很好。我的属性网格实际上与VS属性网格类似 我的问题是,每次使用更改选定对象(这会导致属性网格中的更改)都需要花费大量时间(取决于选定对象属性的数量)。我发现性能不好的原因是模板加载和渲染。 所以我想我可以通过为每个对象创建真正的控件来解决这个问题,而不仅仅是使用模板。(为每个属性创建按钮和文本框)我希望这将解决加载时间问题 1-是否有任何方法可以使用数据模板创建真正的控件(在代码中)? 2-是否有其他方法来提高我的物业网格的性能 propGrid的主要代码附在本文之后 谢谢你,里昂 代码:Wpf 渲染模板性能,wpf,performance,datatemplate,Wpf,Performance,Datatemplate,我创建了一个类似propertyGrid的。 我使用了一个使用viewmodel对象的项控件。 VM对象具有要显示的属性及其相关的DataTemplates。 一切都很好。我的属性网格实际上与VS属性网格类似 我的问题是,每次使用更改选定对象(这会导致属性网格中的更改)都需要花费大量时间(取决于选定对象属性的数量)。我发现性能不好的原因是模板加载和渲染。 所以我想我可以通过为每个对象创建真正的控件来解决这个问题,而不仅仅是使用模板。(为每个属性创建按钮和文本框)我希望这将解决加载时间问题 1-是
更新:这是容器
<ItemsControl Name="propsDataGrid" ItemsSource="{Binding Properties}" ItemTemplate ="{StaticResource gridItemsControl}">
<ItemsControl.ContextMenu>
<ContextMenu>
<MenuItem Header="Close all expanders" Click="MenuItem_Click" Visibility="{Binding IsAlphaBeticSort,Converter={StaticResource boolToVisConverter},ConverterParameter=VisForFalse}"></MenuItem>
<MenuItem Header="Expand all" Name="mnExpandeAll" Click="mnExpandeAll_Click" Visibility="{Binding IsAlphaBeticSort,Converter={StaticResource boolToVisConverter},ConverterParameter=VisForFalse}"></MenuItem>
</ContextMenu>
</ItemsControl.ContextMenu>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!--<ItemsControl.ItemTemplate>
<DataTemplate >
<Grid Visibility="{Binding Visibility}">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="60" MaxWidth="350" Width="{Binding Source={StaticResource firstCulWidth},Path=Width,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,Converter={StaticResource widthToGridLenConverter}}"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="#ff333333" BorderThickness="0.5" Grid.ColumnSpan="2"
Visibility ="{Binding IsCategoryItem,Converter={StaticResource isCategoryItemToVisibilityConverter},ConverterParameter=Category}">
<StackPanel Orientation="Horizontal" Background="#FFA9BFD4" Height="25">
<Expander Template="{StaticResource SimpleExpanderTemp}" ExpandDirection="Left" IsExpanded="{Binding IsExpanded, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Margin="3,0,5,0"/>
<Label Content="{Binding Path=CategoryName,Converter={StaticResource propertyNameToDiplayNameConverter}}" FontSize="12" Foreground="White" VerticalAlignment="Top" />
</StackPanel>
</Border>
<Border Grid.Column="0" BorderBrush="#ff333333" BorderThickness="0.5"
Visibility ="{Binding IsCategoryItem,Converter={StaticResource isCategoryItemToVisibilityConverter}}">
<Label Margin="5,0,0,0" Content="{Binding Path=DisplayName,Converter={StaticResource propertyNameToDiplayNameConverter}}"/>
</Border>
<GridSplitter Grid.Row="0" Grid.Column="0" Visibility ="{Binding IsCategoryItem,Converter={StaticResource isCategoryItemToVisibilityConverter}}" HorizontalAlignment="Right" Width="4" Background="Transparent"/>
<Border Grid.Column="1" BorderBrush="#ff333333" BorderThickness="0.5"
Visibility ="{Binding IsCategoryItem,Converter={StaticResource isCategoryItemToVisibilityConverter}}">
<ContentPresenter Grid.Column="1" Margin="10,1,10,1" HorizontalAlignment="Left"
ContentTemplate="{Binding Path=InlineTemplate}" />
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>-->
</ItemsControl>
数据模板
创建“真正的控件”手动操作(使用模板自动完成)没有任何好处,您唯一需要担心的是虚拟化(以便不创建视图中属性的控件)以及模板的连接方式,以避免不必要地触发它们的创建
(顺便说一句,您创建栅格的方式,设置栅格宽度,看起来可能是多余的,您可能只需要这样做。)
要创建ItemsControl
虚拟化所需的项目,请执行以下操作:
ItemsPanel
设置为ItemsPresenter
周围有一个控件模板,其中包含一个ScrollViewer
,其中将显示VirtualizangStackPanel
ScrollViewer.CanContentScroll
设置为true
,以启用按项滚动,从而允许虚拟化
如果这仍然太慢,您可以使整个
ItemsControl
成为适用于每种类型的模板的一部分,因为此网格的内容可能取决于项目的类型,因此只有在项目类型更改时才应创建不同的网格,您也可以缓存生成的模板(尽管我从未尝试过这样做)。包含/生成项目的控件是如何定义的?感谢H.B的重播,我想这样做的原因是避免创建那些控件(由临时创建的)不止一个。每次用户选择查看某个对象的属性时,我的属性网格都会加载/使用数据模板,因此我想通过为我的每个数据对象一次装入UIElements来改进这一点。@Leonoah:您可能绑定了一些错误的内容,而且您似乎错过了虚拟化的部分,仍然没有执行任何操作请不要提供容器的定义,这可以解释为什么您可能没有任何虚拟化。再次感谢H.B,我更新了帖子并添加了conatiner代码。@leonnoah:如果您定义了一个ItemsControl这样的控件,所有的项都将一次创建,我添加了一个关于虚拟化的示例,但这当然只有在您的网格足够多的项,其中一些项将被删除(如果在应用示例时,ItemsControl周围有一个scrollviewer,则应删除该项)。谢谢你,agian H.B!。我已经实现了VirtualzingStackPanel,但当我想显示其他对象的属性时,加载会持续大约1秒钟。我确信模板存在一些问题。我最大的问题是,对于我想显示的每个对象,其属性都有不同类型的数据,因此每次s使用不同的模板。控件的datacontext是某个Viewmodel的集合,该集合封装了模型(属性数据)及其相关的DataTemple。通过这种方式,我实现了PropertyGrid控件。我的concept错了吗?
<ItemsControl Name="propsDataGrid" ItemsSource="{Binding Properties}" ItemTemplate ="{StaticResource gridItemsControl}">
<ItemsControl.ContextMenu>
<ContextMenu>
<MenuItem Header="Close all expanders" Click="MenuItem_Click" Visibility="{Binding IsAlphaBeticSort,Converter={StaticResource boolToVisConverter},ConverterParameter=VisForFalse}"></MenuItem>
<MenuItem Header="Expand all" Name="mnExpandeAll" Click="mnExpandeAll_Click" Visibility="{Binding IsAlphaBeticSort,Converter={StaticResource boolToVisConverter},ConverterParameter=VisForFalse}"></MenuItem>
</ContextMenu>
</ItemsControl.ContextMenu>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!--<ItemsControl.ItemTemplate>
<DataTemplate >
<Grid Visibility="{Binding Visibility}">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="60" MaxWidth="350" Width="{Binding Source={StaticResource firstCulWidth},Path=Width,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,Converter={StaticResource widthToGridLenConverter}}"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="#ff333333" BorderThickness="0.5" Grid.ColumnSpan="2"
Visibility ="{Binding IsCategoryItem,Converter={StaticResource isCategoryItemToVisibilityConverter},ConverterParameter=Category}">
<StackPanel Orientation="Horizontal" Background="#FFA9BFD4" Height="25">
<Expander Template="{StaticResource SimpleExpanderTemp}" ExpandDirection="Left" IsExpanded="{Binding IsExpanded, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Margin="3,0,5,0"/>
<Label Content="{Binding Path=CategoryName,Converter={StaticResource propertyNameToDiplayNameConverter}}" FontSize="12" Foreground="White" VerticalAlignment="Top" />
</StackPanel>
</Border>
<Border Grid.Column="0" BorderBrush="#ff333333" BorderThickness="0.5"
Visibility ="{Binding IsCategoryItem,Converter={StaticResource isCategoryItemToVisibilityConverter}}">
<Label Margin="5,0,0,0" Content="{Binding Path=DisplayName,Converter={StaticResource propertyNameToDiplayNameConverter}}"/>
</Border>
<GridSplitter Grid.Row="0" Grid.Column="0" Visibility ="{Binding IsCategoryItem,Converter={StaticResource isCategoryItemToVisibilityConverter}}" HorizontalAlignment="Right" Width="4" Background="Transparent"/>
<Border Grid.Column="1" BorderBrush="#ff333333" BorderThickness="0.5"
Visibility ="{Binding IsCategoryItem,Converter={StaticResource isCategoryItemToVisibilityConverter}}">
<ContentPresenter Grid.Column="1" Margin="10,1,10,1" HorizontalAlignment="Left"
ContentTemplate="{Binding Path=InlineTemplate}" />
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>-->
</ItemsControl>
<ItemsControl ItemsSource="{Binding Items}"
ScrollViewer.CanContentScroll="True">
<ItemsControl.Template>
<ControlTemplate>
<Border Name="Bd" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true"
Padding="1">
<ScrollViewer Padding="{TemplateBinding Padding}" Focusable="false">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- ... -->
</ItemsControl>