C# wpf如何在scrollviewer的虚拟化stackpanel中对所有可见容器调用度量
目标:重新测量,然后仅重新绘制scrollviewer的虚拟化堆栈面板中显示的信号图 当前版本: 目前,我有一个依赖属性(UnitSoftTimePeraxisDivision),每当scrollviewer(signalgraph)中的容器更新时,它都会影响度量C# wpf如何在scrollviewer的虚拟化stackpanel中对所有可见容器调用度量,c#,wpf,layout,scrollviewer,virtualizingstackpanel,C#,Wpf,Layout,Scrollviewer,Virtualizingstackpanel,目标:重新测量,然后仅重新绘制scrollviewer的虚拟化堆栈面板中显示的信号图 当前版本: 目前,我有一个依赖属性(UnitSoftTimePeraxisDivision),每当scrollviewer(signalgraph)中的容器更新时,它都会影响度量 public static readonly DependencyProperty UnitsOfTimePerAxisDivisionProperty = DependencyProperty.Register("Uni
public static readonly DependencyProperty UnitsOfTimePerAxisDivisionProperty =
DependencyProperty.Register("UnitsOfTimePerAxisDivision",
typeof(int), typeof(SignalGraph),
new FrameworkPropertyMetadata(1), FrameworkPropertyMetadataOptions.AffectsMeasure);
但是,这会更新每个信号图,包括不可见的信号图。在每个信号上运行测量然后重新绘制太耗时了
ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollContentPresenter
Grid.Column="0"
Grid.Row="0" />
<ScrollBar
Margin="{Binding RelativeSource={RelativeSource AncestorType={x:Type DaedalusGraphViewer:GraphViewer}},
Path=GraphHeight, Converter={StaticResource ScrollBarTopMarginConverter}}"
Grid.Row="0"
Grid.Column="1"
Width="18"
Name="PART_VerticalScrollBar"
Orientation="Vertical"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
<ScrollBar
Height="18"
Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Grid.Column="0"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
但是,我发现当我在scrollviewer和signalgraph的度量覆盖中设置断点时,signalgraph中的断点没有被命中
如果重新测量scrollviewer,我不理解为什么不重新测量信号图
<!--Style for scrollviewer for signals-->
<Style x:Key="SignalScrollViewerStyle" TargetType="{x:Type Components:SignalScrollViewer}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollContentPresenter
Grid.Column="0"
Grid.Row="0" />
<ScrollBar
Margin="{Binding RelativeSource={RelativeSource AncestorType={x:Type DaedalusGraphViewer:GraphViewer}},
Path=GraphHeight, Converter={StaticResource ScrollBarTopMarginConverter}}"
Grid.Row="0"
Grid.Column="1"
Width="18"
Name="PART_VerticalScrollBar"
Orientation="Vertical"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
<ScrollBar
Height="18"
Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Grid.Column="0"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
编辑2:
在此页上找到解决方案:
我在此页面上找到了解决方案:
"
当覆盖默认的scrollviewer样式时,我没有将附加属性绑定到scrollviewer contentpresenter。uggh,这一行很难找到。我简直疯了,以为我不知道虚拟化到底应该做什么
现在唯一令人烦恼的是,我仍然不完全理解布局过程是如何工作的。如果我有一个带有metadaoption affectsmeasure的依赖项属性,然后该依赖项属性更改,则该项将重新测量。如果元素的大小更改,父项是否会重新测量
这可能是我的猜测,但它仍然无法解释为什么在scrollviewer的测量周期中,scrollviewer的子项没有重新测量。使用Reflector没有任何意义。VirtualzingStackPanel维护一个可见容器的列表。当您开始上下滚动时,VirtualzingStackPanel将移除容器这将不再需要,但会创建一个新的。最后删除5个旧项目,但添加5个新项目,因此可见容器的计数始终保持不变,因此只需更改UnitSoftTimePeraxisDivision属性,而不必担心哪些容器可见 如果ScrollViewer将90x90传递给VirtualzingStackPanel,并且VirtualzingStackPanel将无限传递给容器,则容器将仅在处于无效测量状态时重新测量,否则它们将返回其当前大小的“旧”大小
只需让WPF完成这项工作,不要担心性能问题。VirtualzingStackPanel包含可见的容器,因此不会对所有可能的容器进行任何重新测量或性能影响。即使您有1000项,也只会使用20项。因此问题是我未能将cancontentscroll属性附加到我的scrollcont我的scrollviewer样式的ent演示者
<ScrollContentPresenter
CanContentScroll="{TemplateBinding ScrollViewer.CanContentScroll}"
抱歉,我仍然不太明白当虚拟化堆栈面板正常工作时会发生什么。我不确定是否正确设置了它。1.虚拟化堆栈面板会测量其中的每个项目,还是只测量到它填满了可用空间?2.虚拟化堆栈面板会执行吗在每个项目上?在我的程序中,我看到它创建所有信号图并测量它们。我想我不知道UI虚拟化的真正含义。什么是UI虚拟化?a.面板不会渲染超出范围的元素,但仍会在面板中的所有项目上创建并执行所有布局计算。b.面板仅在填充之前创建对象我的理解是虚拟化Zingstack面板提供了后者
<ScrollContentPresenter
CanContentScroll="{TemplateBinding ScrollViewer.CanContentScroll}"