最近我遇到了一个虚拟化问题,我把它缩小到了下面的代码。
虚拟化之所以不能在下面的代码段中工作,是因为子程序没有特定的高度。因此,我猜想它会永远扩展,而虚拟化就会中断。
给子对象一个特定的高度可以解决这个问题,但是当我想要一个滚动条时,界面就变成了两个难看的滚动条,可以滚动条目控件生成的全部内容(如果是子控件,或者不是子项)。
我的问题是,这可能吗?如果是这样的话,我怎样才能做到呢?不知何故,子程序需要计算自己的大小,而不破坏虚拟化。设置*的高度似乎不起作用。
MainWindow.xaml
<Window x:Class="WpfItemsControlVirtualization.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="500" >
<Window.Resources>
<ResourceDictionary>
<!--Virtualised ItemsControl-->
<Style x:Key="ItemsControlVirtialisedStyle" TargetType="ItemsControl">
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="Go" Click="ButtonBase_OnClick"/>
<Button Grid.Row="1" Content="Expand" Click="ButtonBase_OnClick2"/>
<Expander Grid.Row="2" >
<ItemsControl ItemsSource="{Binding Collection}" Style="{StaticResource ItemsControlVirtialisedStyle}" VirtualizingPanel.ScrollUnit="Pixel">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<!-- <RowDefinition Height="*"></RowDefinition> --> <!-- VIRTUALIZATION BREAK -->
<RowDefinition Height="500"></RowDefinition>
</Grid.RowDefinitions>
<ItemsControl ItemsSource="{Binding Collection}" Style="{StaticResource ItemsControlVirtialisedStyle}" VirtualizingPanel.ScrollUnit="Pixel">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Test}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Expander>
</Grid>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfItemsControlVirtualization
{
/// <summary>
/// Implements the INotifyPropertyChanged interface for data binding purposes.
/// </summary>
public abstract class ViewModelBase : INotifyPropertyChanged, INotifyPropertyChanging
{
#region Abstract
public void AlertPropertyChanging(string propertyName)
{
OnPropertyChanging(propertyName);
}
public void AlertPropertyChanged(string propertyName)
{
OnPropertyChanged(propertyName);
}
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected void OnPropertyChanging(string propertyName)
{
var handler = PropertyChanging;
if (handler != null) handler(this, new PropertyChangingEventArgs(propertyName));
}
protected bool Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
OnPropertyChanging(propertyName);
field = value;
OnPropertyChanged(propertyName);
return true;
}
protected void Set(Action action, string propertyName = null)
{
OnPropertyChanging(propertyName);
if (action != null) action();
OnPropertyChanged(propertyName);
}
#endregion
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
#endregion Implementation of INotifyPropertyChanged
#region Implementation of INotifyPropertyChanging
public event PropertyChangingEventHandler PropertyChanging;
#endregion Implementation of INotifyPropertyChanging
}
public class MySubDataTest : ViewModelBase
{
public MySubDataTest()
{
}
public string Test
{
get { return "SubTest"; }
set { }
}
public bool IsExpanded
{
get { return m_IsExpanded; }
set { Set(ref m_IsExpanded, value); }
}
private bool m_IsExpanded = false;
}
public class MyDataTest : ViewModelBase
{
public MyDataTest()
{
int test = 1000;
for (int i = 0; i < test; i++)
{
Collection.Add(new MySubDataTest());
}
}
public string Test
{
get { return "Test"; }
set { }
}
public bool IsExpanded
{
get { return m_IsExpanded; }
set { Set(ref m_IsExpanded, value); }
}
private bool m_IsExpanded = false;
public ObservableCollection<MySubDataTest> Collection
{
get { return m_Collection; }
}
ObservableCollection<MySubDataTest> m_Collection = new ObservableCollection<MySubDataTest>();
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public ObservableCollection<MyDataTest> Collection
{
get { return m_Collection; }
}
ObservableCollection<MyDataTest> m_Collection = new ObservableCollection<MyDataTest>();
private void ButtonBase_OnClick(object _sender, RoutedEventArgs _e)
{
int count = 1;
for (var i = 0; i < count; i++)
{
Collection.Add(new MyDataTest());
}
DataContext = this;
}
private void ButtonBase_OnClick2(object _sender, RoutedEventArgs _e)
{
foreach (MyDataTest test in Collection)
{
foreach (MySubDataTest sub in test.Collection)
{
sub.IsExpanded = true;
}
test.IsExpanded = true;
}
}
}
}提前谢谢你。
发布于 2016-04-29 08:48:34
没有现成的方法来做这件事。我最后这样做的方式是完全定制TreeView的模板,因为它支持继承虚拟化。
您可以与DataTemplates一起使用它来产生与递归ItemsTemplates相同的结果,并且它的效率要高得多。
发布于 2016-07-28 13:27:16
这里没问题。外部ItemsControl的ItemsControl本身包含一个ItemsControl。在ItemsControl中,每个元素要么呈现,要么不呈现。虚拟化可能有助于不呈现不可见的元素,但是第一个元素是部分可见的,因此它不符合虚拟化的条件,并且完全以无限的高度呈现。
https://stackoverflow.com/questions/36692164
复制相似问题