VirtualizingPanel 停止在 Viewbox 中工作的 ScrollViewer
VirtualizingPanel stops ScrollViewer working within Viewbox
我有一个简单的自定义面板,托管在 ItemsControl
的 ItemsPanel
中。 ItemsControl
的 Template
更新为用 Viewbox
和 ScrollViewer
包围 ItemsPresenter
。这是 XAML 代码:
<ItemsControl ItemsSource="{Binding Buttons, RelativeSource={RelativeSource
AncestorType={x:Type Local:MainWindow}}}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.CanContentScroll="True">
<ItemsControl.Template>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<ScrollViewer CanContentScroll="True">
<Viewbox Stretch="UniformToFill">
<ItemsPresenter />
</Viewbox>
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Local:TestPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Height="250" Width="250" HorizontalAlignment="Center"
Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
和 Panel
:
public class TestPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
var desiredSize = new Size();
var layoutSlotSize = availableSize;
layoutSlotSize.Height = double.PositiveInfinity;
for (int i = 0, count = InternalChildren.Count; i < count; ++i)
{
UIElement child = InternalChildren[i];
if (child == null) continue;
child.Measure(layoutSlotSize);
var childDesiredSize = child.DesiredSize;
desiredSize.Width = Math.Max(desiredSize.Width, childDesiredSize.Width);
desiredSize.Height += childDesiredSize.Height;
}
return desiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
double verticalOffset = 0;
for (int i = 0, count = InternalChildren.Count; i < count; ++i)
{
UIElement child = InternalChildren[i];
if (child == null) continue;
child.Arrange(new Rect(0, verticalOffset, child.DesiredSize.Width,
child.DesiredSize.Height));
verticalOffset += child.DesiredSize.Height;
}
return base.ArrangeOverride(finalSize);
}
}
最后,MainWindow.xaml.cs
:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Buttons = new ObservableCollection<string>();
IEnumerable<int> characterCodes = Enumerable.Range(65, 26);
foreach (int characterCode in characterCodes)
Buttons.Add(((char)characterCode).ToString().ToUpper());
}
public static readonly DependencyProperty ButtonsProperty =
DependencyProperty.Register(nameof(Buttons), typeof(ObservableCollection<string>),
typeof(MainWindow), null);
public ObservableCollection<string> Buttons
{
get { return (ObservableCollection<string>)GetValue(ButtonsProperty); }
set { SetValue(ButtonsProperty, value); }
}
}
这一切都按预期工作...到目前为止,一切顺利。问题是当我将基础 class 从 Panel
更改为 VirtualizingPanel
时,我需要这样做来虚拟化数据(不是这个示例按钮数据)。更改基数 class 后,面板立即停止工作。我完全知道如何在面板中虚拟化数据......我有一个工作示例。我的问题是当我想在 ScrollViewer
中添加一个 Viewbox
时。
请注意,这个 XAML 可以与正常的 Panel
或 StackPanel
一起正常工作,但是一旦我将其更改为 VirtualizingPanel
,它就会停止工作(不呈现任何内容,并且 InternalChildren
属性 不包含任何元素)。谁能帮我解释一下这个问题?
我仍然不知道为什么 VirtualizingPanel
在 ScrollViewer
中的 ViewBox
中不起作用,但我发现如果我扩展 VirtualizingStackPanel
class 在我的面板中,一切都按预期工作。
因此,对于那些需要堆叠虚拟化项目的人来说,解决方案是扩展 VirtualizingStackPanel
class。对于那些需要其他类型子排列的人,很抱歉,但我没有答案,除非你删除 Viewbox
.
我仍然非常乐意收到有关此主题的任何进一步信息。
我有一个简单的自定义面板,托管在 ItemsControl
的 ItemsPanel
中。 ItemsControl
的 Template
更新为用 Viewbox
和 ScrollViewer
包围 ItemsPresenter
。这是 XAML 代码:
<ItemsControl ItemsSource="{Binding Buttons, RelativeSource={RelativeSource
AncestorType={x:Type Local:MainWindow}}}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.CanContentScroll="True">
<ItemsControl.Template>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<ScrollViewer CanContentScroll="True">
<Viewbox Stretch="UniformToFill">
<ItemsPresenter />
</Viewbox>
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Local:TestPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Height="250" Width="250" HorizontalAlignment="Center"
Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
和 Panel
:
public class TestPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
var desiredSize = new Size();
var layoutSlotSize = availableSize;
layoutSlotSize.Height = double.PositiveInfinity;
for (int i = 0, count = InternalChildren.Count; i < count; ++i)
{
UIElement child = InternalChildren[i];
if (child == null) continue;
child.Measure(layoutSlotSize);
var childDesiredSize = child.DesiredSize;
desiredSize.Width = Math.Max(desiredSize.Width, childDesiredSize.Width);
desiredSize.Height += childDesiredSize.Height;
}
return desiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
double verticalOffset = 0;
for (int i = 0, count = InternalChildren.Count; i < count; ++i)
{
UIElement child = InternalChildren[i];
if (child == null) continue;
child.Arrange(new Rect(0, verticalOffset, child.DesiredSize.Width,
child.DesiredSize.Height));
verticalOffset += child.DesiredSize.Height;
}
return base.ArrangeOverride(finalSize);
}
}
最后,MainWindow.xaml.cs
:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Buttons = new ObservableCollection<string>();
IEnumerable<int> characterCodes = Enumerable.Range(65, 26);
foreach (int characterCode in characterCodes)
Buttons.Add(((char)characterCode).ToString().ToUpper());
}
public static readonly DependencyProperty ButtonsProperty =
DependencyProperty.Register(nameof(Buttons), typeof(ObservableCollection<string>),
typeof(MainWindow), null);
public ObservableCollection<string> Buttons
{
get { return (ObservableCollection<string>)GetValue(ButtonsProperty); }
set { SetValue(ButtonsProperty, value); }
}
}
这一切都按预期工作...到目前为止,一切顺利。问题是当我将基础 class 从 Panel
更改为 VirtualizingPanel
时,我需要这样做来虚拟化数据(不是这个示例按钮数据)。更改基数 class 后,面板立即停止工作。我完全知道如何在面板中虚拟化数据......我有一个工作示例。我的问题是当我想在 ScrollViewer
中添加一个 Viewbox
时。
请注意,这个 XAML 可以与正常的 Panel
或 StackPanel
一起正常工作,但是一旦我将其更改为 VirtualizingPanel
,它就会停止工作(不呈现任何内容,并且 InternalChildren
属性 不包含任何元素)。谁能帮我解释一下这个问题?
我仍然不知道为什么 VirtualizingPanel
在 ScrollViewer
中的 ViewBox
中不起作用,但我发现如果我扩展 VirtualizingStackPanel
class 在我的面板中,一切都按预期工作。
因此,对于那些需要堆叠虚拟化项目的人来说,解决方案是扩展 VirtualizingStackPanel
class。对于那些需要其他类型子排列的人,很抱歉,但我没有答案,除非你删除 Viewbox
.
我仍然非常乐意收到有关此主题的任何进一步信息。