最近仮想化の問題に遭遇し、以下のコードに絞り込んだ。ItemsControl内で高さが*のItemsControlを仮想化
次のスニペットで仮想化が機能しないのは、子が特定の高さを持たないためです。だから私の推測は、それが永遠に拡大し、仮想化が破綻するということです。
子を特定の高さに設定すると問題が解決されますが、スクロールバーが1つの場合はインターフェイスが2つの目障りなスクロールバーになり、アイテムコントロールによって生成されたコンテンツ全体をスクロールします。
私の質問は、これは可能ですか?もしそうなら、私はこれをどのように達成できますか?どうやら、子供は仮想化を破ることなく、自分自身のサイズを計算する必要があります。 *の高さを設定するとうまくいかないようです。
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;
}
}
}
}
事前にありがとうございます。
これは私が上で解決した問題があった私の質問に答えない – Asheh
_私の質問は、これは可能ですか?_私の答えは "いいえ"です。 ItemsControlは、直接項目のみを仮想化し、ネストされたItemsControlに含まれる可能性のある項目は仮想化しません。私はあなたがこれをかなり理解しているかどうかは確かではありませんが、あなたがItemsControlが何を期待しているのかはっきりしていますが、**これは設計によって**できません。 – franssu