1
0
Эх сурвалжийг харах

Begin refactoring ItemsPresenter.

A lot still broken, in particular virtualization is completely removed.`ItemsPresenter` now no longer has an `Items` or `ItemTemplate` property; it detects when it's hosted in an `ItemsControl`. `IItemsPresenter` interface removed.
Steven Kirk 2 жил өмнө
parent
commit
692c0c155d
64 өөрчлөгдсөн 3040 нэмэгдсэн , 5086 устгасан
  1. 294 294
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  2. 1 3
      samples/SampleControls/HamburgerMenu/HamburgerMenu.xaml
  3. 1 4
      src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml
  4. 1 4
      src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml
  5. 1 1
      src/Avalonia.Controls/ComboBox.cs
  6. 0 78
      src/Avalonia.Controls/IVirtualizingPanel.cs
  7. 2 10
      src/Avalonia.Controls/ItemsControl.cs
  8. 1 1
      src/Avalonia.Controls/ListBox.cs
  9. 172 172
      src/Avalonia.Controls/Presenters/CarouselPresenter.cs
  10. 0 18
      src/Avalonia.Controls/Presenters/IItemsPresenter.cs
  11. 2 2
      src/Avalonia.Controls/Presenters/IItemsPresenterHost.cs
  12. 0 125
      src/Avalonia.Controls/Presenters/ItemContainerSync.cs
  13. 0 303
      src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
  14. 0 106
      src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs
  15. 0 606
      src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
  16. 48 139
      src/Avalonia.Controls/Presenters/ItemsPresenter.cs
  17. 0 308
      src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs
  18. 108 0
      src/Avalonia.Controls/Presenters/ItemsPresenterContainerGenerator.cs
  19. 1 1
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  20. 10 242
      src/Avalonia.Controls/VirtualizingStackPanel.cs
  21. 0 1
      src/Avalonia.Themes.Fluent/Controls/Carousel.xaml
  22. 1 4
      src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml
  23. 0 2
      src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml
  24. 1 3
      src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml
  25. 1 4
      src/Avalonia.Themes.Fluent/Controls/ListBox.xaml
  26. 1 4
      src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml
  27. 0 4
      src/Avalonia.Themes.Fluent/Controls/Menu.xaml
  28. 0 2
      src/Avalonia.Themes.Fluent/Controls/MenuFlyoutPresenter.xaml
  29. 0 2
      src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml
  30. 0 2
      src/Avalonia.Themes.Fluent/Controls/TabControl.xaml
  31. 1 3
      src/Avalonia.Themes.Fluent/Controls/TabStrip.xaml
  32. 0 1
      src/Avalonia.Themes.Fluent/Controls/TreeView.xaml
  33. 0 1
      src/Avalonia.Themes.Fluent/Controls/TreeViewItem.xaml
  34. 0 1
      src/Avalonia.Themes.Simple/Controls/Carousel.xaml
  35. 1 4
      src/Avalonia.Themes.Simple/Controls/ComboBox.xaml
  36. 0 2
      src/Avalonia.Themes.Simple/Controls/ContextMenu.xaml
  37. 0 2
      src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml
  38. 1 4
      src/Avalonia.Themes.Simple/Controls/ListBox.xaml
  39. 0 4
      src/Avalonia.Themes.Simple/Controls/Menu.xaml
  40. 0 2
      src/Avalonia.Themes.Simple/Controls/MenuFlyoutPresenter.xaml
  41. 0 2
      src/Avalonia.Themes.Simple/Controls/MenuItem.xaml
  42. 0 2
      src/Avalonia.Themes.Simple/Controls/TabControl.xaml
  43. 0 2
      src/Avalonia.Themes.Simple/Controls/TabStrip.xaml
  44. 0 1
      src/Avalonia.Themes.Simple/Controls/TreeView.xaml
  45. 0 1
      src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml
  46. 0 1
      tests/Avalonia.Controls.UnitTests/CarouselTests.cs
  47. 0 1
      tests/Avalonia.Controls.UnitTests/ComboBoxTests.cs
  48. 1 3
      tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs
  49. 26 26
      tests/Avalonia.Controls.UnitTests/ListBoxTests.cs
  50. 0 1
      tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs
  51. 0 1
      tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs
  52. 732 732
      tests/Avalonia.Controls.UnitTests/Presenters/CarouselPresenterTests.cs
  53. 85 285
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs
  54. 374 374
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs
  55. 911 911
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs
  56. 1 4
      tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
  57. 0 2
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs
  58. 0 1
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs
  59. 0 1
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs
  60. 0 1
      tests/Avalonia.Controls.UnitTests/Primitives/TabStripTests.cs
  61. 0 2
      tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
  62. 261 261
      tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs
  63. 0 1
      tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs
  64. 0 1
      tests/Avalonia.UnitTests/TestExtensions.cs

+ 294 - 294
samples/ControlCatalog/Pages/DialogsPage.xaml.cs

@@ -24,301 +24,301 @@ namespace ControlCatalog.Pages
         {
             this.InitializeComponent();
 
-            var results = this.Get<ItemsPresenter>("PickerLastResults");
-            var resultsVisible = this.Get<TextBlock>("PickerLastResultsVisible");
-            var bookmarkContainer = this.Get<TextBox>("BookmarkContainer");
-            var openedFileContent = this.Get<TextBox>("OpenedFileContent");
-            var openMultiple = this.Get<CheckBox>("OpenMultiple");
-
-            IStorageFolder? lastSelectedDirectory = null;
-
-            List<FileDialogFilter> GetFilters()
-            {
-                if (this.Get<CheckBox>("UseFilters").IsChecked != true)
-                    return new List<FileDialogFilter>();
-                return  new List<FileDialogFilter>
-                {
-                    new FileDialogFilter
-                    {
-                        Name = "Text files (.txt)", Extensions = new List<string> {"txt"}
-                    },
-                    new FileDialogFilter
-                    {
-                        Name = "All files",
-                        Extensions = new List<string> {"*"}
-                    }
-                };
-            }
-
-            List<FilePickerFileType>? GetFileTypes()
-            {
-                if (this.Get<CheckBox>("UseFilters").IsChecked != true)
-                    return null;
-                return new List<FilePickerFileType>
-                {
-                    FilePickerFileTypes.All,
-                    FilePickerFileTypes.TextPlain
-                };
-            }
-
-            this.Get<Button>("OpenFile").Click += async delegate
-            {
-                // Almost guaranteed to exist
-                var uri = Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName;
-                var initialFileName = uri == null ? null : System.IO.Path.GetFileName(uri);
-                var initialDirectory = uri == null ? null : System.IO.Path.GetDirectoryName(uri);
-
-                var result = await new OpenFileDialog()
-                {
-                    Title = "Open file",
-                    Filters = GetFilters(),
-                    Directory = initialDirectory,
-                    InitialFileName = initialFileName
-                }.ShowAsync(GetWindow());
-                results.Items = result;
-                resultsVisible.IsVisible = result?.Any() == true;
-            };
-            this.Get<Button>("OpenMultipleFiles").Click += async delegate
-            {
-                var result = await new OpenFileDialog()
-                {
-                    Title = "Open multiple files",
-                    Filters = GetFilters(),
-                    Directory = lastSelectedDirectory?.TryGetUri(out var path) == true ? path.LocalPath : null,
-                    AllowMultiple = true
-                }.ShowAsync(GetWindow());
-                results.Items = result;
-                resultsVisible.IsVisible = result?.Any() == true;
-            };
-            this.Get<Button>("SaveFile").Click += async delegate
-            {
-                var filters = GetFilters();
-                var result = await new SaveFileDialog()
-                {
-                    Title = "Save file",
-                    Filters = filters,
-                    Directory = lastSelectedDirectory?.TryGetUri(out var path) == true ? path.LocalPath : null,
-                    DefaultExtension = filters?.Any() == true ? "txt" : null,
-                    InitialFileName = "test.txt"
-                }.ShowAsync(GetWindow());
-                results.Items = new[] { result };
-                resultsVisible.IsVisible = result != null;
-            };
-            this.Get<Button>("SelectFolder").Click += async delegate
-            {
-                var result = await new OpenFolderDialog()
-                {
-                    Title = "Select folder",
-                    Directory = lastSelectedDirectory?.TryGetUri(out var path) == true ? path.LocalPath : null
-                }.ShowAsync(GetWindow());
-                if (string.IsNullOrEmpty(result))
-                {
-                    resultsVisible.IsVisible = false;
-                }
-                else
-                {
-                    lastSelectedDirectory = new BclStorageFolder(new System.IO.DirectoryInfo(result));
-                    results.Items = new[] { result };
-                    resultsVisible.IsVisible = true;
-                }
-            };
-            this.Get<Button>("OpenBoth").Click += async delegate
-            {
-                var result = await new OpenFileDialog()
-                {
-                    Title = "Select both",
-                    Directory = lastSelectedDirectory?.TryGetUri(out var path) == true ? path.LocalPath : null,
-                    AllowMultiple = true
-                }.ShowManagedAsync(GetWindow(), new ManagedFileDialogOptions
-                {
-                    AllowDirectorySelection = true
-                });
-                results.Items = result;
-                resultsVisible.IsVisible = result?.Any() == true;
-            };
-            this.Get<Button>("DecoratedWindow").Click += delegate
-            {
-                new DecoratedWindow().Show();
-            };
-            this.Get<Button>("DecoratedWindowDialog").Click += delegate
-            {
-                _ = new DecoratedWindow().ShowDialog(GetWindow());
-            };
-            this.Get<Button>("Dialog").Click += delegate
-            {
-                var window = CreateSampleWindow();
-                window.Height = 200;
-                _ = window.ShowDialog(GetWindow());
-            };
-            this.Get<Button>("DialogNoTaskbar").Click += delegate
-            {
-                var window = CreateSampleWindow();
-                window.Height = 200;
-                window.ShowInTaskbar = false;
-                _ = window.ShowDialog(GetWindow());
-            };
-            this.Get<Button>("OwnedWindow").Click += delegate
-            {
-                var window = CreateSampleWindow();
-
-                window.Show(GetWindow());
-            };
-
-            this.Get<Button>("OwnedWindowNoTaskbar").Click += delegate
-            {
-                var window = CreateSampleWindow();
-
-                window.ShowInTaskbar = false;
-
-                window.Show(GetWindow());
-            };
-
-            this.Get<Button>("OpenFilePicker").Click += async delegate
-            {
-                var result = await GetStorageProvider().OpenFilePickerAsync(new FilePickerOpenOptions()
-                {
-                    Title = "Open file",
-                    FileTypeFilter = GetFileTypes(),
-                    SuggestedStartLocation = lastSelectedDirectory,
-                    AllowMultiple = openMultiple.IsChecked == true
-                });
-
-                await SetPickerResult(result);
-            };
-            this.Get<Button>("SaveFilePicker").Click += async delegate
-            {
-                var fileTypes = GetFileTypes();
-                var file = await GetStorageProvider().SaveFilePickerAsync(new FilePickerSaveOptions()
-                {
-                    Title = "Save file",
-                    FileTypeChoices = fileTypes,
-                    SuggestedStartLocation = lastSelectedDirectory,
-                    SuggestedFileName = "FileName",
-                    DefaultExtension = fileTypes?.Any() == true ? "txt" : null,
-                    ShowOverwritePrompt = false
-                });
-
-                if (file is not null && file.CanOpenWrite)
-                {
-                    // Sync disposal of StreamWriter is not supported on WASM
-#if NET6_0_OR_GREATER
-                    await using var stream = await file.OpenWriteAsync();
-                    await using var reader = new System.IO.StreamWriter(stream);
-#else
-                    using var stream = await file.OpenWriteAsync();
-                    using var reader = new System.IO.StreamWriter(stream);
-#endif
-                    await reader.WriteLineAsync(openedFileContent.Text);
-
-                    lastSelectedDirectory = await file.GetParentAsync();
-                }
-
-                await SetPickerResult(file is null ? null : new [] {file});
-            };
-            this.Get<Button>("OpenFolderPicker").Click += async delegate
-            {
-                var folders = await GetStorageProvider().OpenFolderPickerAsync(new FolderPickerOpenOptions()
-                {
-                    Title = "Folder file",
-                    SuggestedStartLocation = lastSelectedDirectory,
-                    AllowMultiple = openMultiple.IsChecked == true
-                });
-
-                await SetPickerResult(folders);
-
-                lastSelectedDirectory = folders.FirstOrDefault();
-            };
-            this.Get<Button>("OpenFileFromBookmark").Click += async delegate
-            {
-                var file = bookmarkContainer.Text is not null
-                    ? await GetStorageProvider().OpenFileBookmarkAsync(bookmarkContainer.Text)
-                    : null;
-
-                await SetPickerResult(file is null ? null : new[] { file });
-            };
-            this.Get<Button>("OpenFolderFromBookmark").Click += async delegate
-            {
-                var folder = bookmarkContainer.Text is not null
-                    ? await GetStorageProvider().OpenFolderBookmarkAsync(bookmarkContainer.Text)
-                    : null;
-
-                await SetPickerResult(folder is null ? null : new[] { folder });
+////            var results = this.Get<ItemsPresenter>("PickerLastResults");
+////            var resultsVisible = this.Get<TextBlock>("PickerLastResultsVisible");
+////            var bookmarkContainer = this.Get<TextBox>("BookmarkContainer");
+////            var openedFileContent = this.Get<TextBox>("OpenedFileContent");
+////            var openMultiple = this.Get<CheckBox>("OpenMultiple");
+
+////            IStorageFolder? lastSelectedDirectory = null;
+
+////            List<FileDialogFilter> GetFilters()
+////            {
+////                if (this.Get<CheckBox>("UseFilters").IsChecked != true)
+////                    return new List<FileDialogFilter>();
+////                return  new List<FileDialogFilter>
+////                {
+////                    new FileDialogFilter
+////                    {
+////                        Name = "Text files (.txt)", Extensions = new List<string> {"txt"}
+////                    },
+////                    new FileDialogFilter
+////                    {
+////                        Name = "All files",
+////                        Extensions = new List<string> {"*"}
+////                    }
+////                };
+////            }
+
+////            List<FilePickerFileType>? GetFileTypes()
+////            {
+////                if (this.Get<CheckBox>("UseFilters").IsChecked != true)
+////                    return null;
+////                return new List<FilePickerFileType>
+////                {
+////                    FilePickerFileTypes.All,
+////                    FilePickerFileTypes.TextPlain
+////                };
+////            }
+
+////            this.Get<Button>("OpenFile").Click += async delegate
+////            {
+////                // Almost guaranteed to exist
+////                var uri = Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName;
+////                var initialFileName = uri == null ? null : System.IO.Path.GetFileName(uri);
+////                var initialDirectory = uri == null ? null : System.IO.Path.GetDirectoryName(uri);
+
+////                var result = await new OpenFileDialog()
+////                {
+////                    Title = "Open file",
+////                    Filters = GetFilters(),
+////                    Directory = initialDirectory,
+////                    InitialFileName = initialFileName
+////                }.ShowAsync(GetWindow());
+////                results.Items = result;
+////                resultsVisible.IsVisible = result?.Any() == true;
+////            };
+////            this.Get<Button>("OpenMultipleFiles").Click += async delegate
+////            {
+////                var result = await new OpenFileDialog()
+////                {
+////                    Title = "Open multiple files",
+////                    Filters = GetFilters(),
+////                    Directory = lastSelectedDirectory?.TryGetUri(out var path) == true ? path.LocalPath : null,
+////                    AllowMultiple = true
+////                }.ShowAsync(GetWindow());
+////                results.Items = result;
+////                resultsVisible.IsVisible = result?.Any() == true;
+////            };
+////            this.Get<Button>("SaveFile").Click += async delegate
+////            {
+////                var filters = GetFilters();
+////                var result = await new SaveFileDialog()
+////                {
+////                    Title = "Save file",
+////                    Filters = filters,
+////                    Directory = lastSelectedDirectory?.TryGetUri(out var path) == true ? path.LocalPath : null,
+////                    DefaultExtension = filters?.Any() == true ? "txt" : null,
+////                    InitialFileName = "test.txt"
+////                }.ShowAsync(GetWindow());
+////                results.Items = new[] { result };
+////                resultsVisible.IsVisible = result != null;
+////            };
+////            this.Get<Button>("SelectFolder").Click += async delegate
+////            {
+////                var result = await new OpenFolderDialog()
+////                {
+////                    Title = "Select folder",
+////                    Directory = lastSelectedDirectory?.TryGetUri(out var path) == true ? path.LocalPath : null
+////                }.ShowAsync(GetWindow());
+////                if (string.IsNullOrEmpty(result))
+////                {
+////                    resultsVisible.IsVisible = false;
+////                }
+////                else
+////                {
+////                    lastSelectedDirectory = new BclStorageFolder(new System.IO.DirectoryInfo(result));
+////                    results.Items = new[] { result };
+////                    resultsVisible.IsVisible = true;
+////                }
+////            };
+////            this.Get<Button>("OpenBoth").Click += async delegate
+////            {
+////                var result = await new OpenFileDialog()
+////                {
+////                    Title = "Select both",
+////                    Directory = lastSelectedDirectory?.TryGetUri(out var path) == true ? path.LocalPath : null,
+////                    AllowMultiple = true
+////                }.ShowManagedAsync(GetWindow(), new ManagedFileDialogOptions
+////                {
+////                    AllowDirectorySelection = true
+////                });
+////                results.Items = result;
+////                resultsVisible.IsVisible = result?.Any() == true;
+////            };
+////            this.Get<Button>("DecoratedWindow").Click += delegate
+////            {
+////                new DecoratedWindow().Show();
+////            };
+////            this.Get<Button>("DecoratedWindowDialog").Click += delegate
+////            {
+////                _ = new DecoratedWindow().ShowDialog(GetWindow());
+////            };
+////            this.Get<Button>("Dialog").Click += delegate
+////            {
+////                var window = CreateSampleWindow();
+////                window.Height = 200;
+////                _ = window.ShowDialog(GetWindow());
+////            };
+////            this.Get<Button>("DialogNoTaskbar").Click += delegate
+////            {
+////                var window = CreateSampleWindow();
+////                window.Height = 200;
+////                window.ShowInTaskbar = false;
+////                _ = window.ShowDialog(GetWindow());
+////            };
+////            this.Get<Button>("OwnedWindow").Click += delegate
+////            {
+////                var window = CreateSampleWindow();
+
+////                window.Show(GetWindow());
+////            };
+
+////            this.Get<Button>("OwnedWindowNoTaskbar").Click += delegate
+////            {
+////                var window = CreateSampleWindow();
+
+////                window.ShowInTaskbar = false;
+
+////                window.Show(GetWindow());
+////            };
+
+////            this.Get<Button>("OpenFilePicker").Click += async delegate
+////            {
+////                var result = await GetStorageProvider().OpenFilePickerAsync(new FilePickerOpenOptions()
+////                {
+////                    Title = "Open file",
+////                    FileTypeFilter = GetFileTypes(),
+////                    SuggestedStartLocation = lastSelectedDirectory,
+////                    AllowMultiple = openMultiple.IsChecked == true
+////                });
+
+////                await SetPickerResult(result);
+////            };
+////            this.Get<Button>("SaveFilePicker").Click += async delegate
+////            {
+////                var fileTypes = GetFileTypes();
+////                var file = await GetStorageProvider().SaveFilePickerAsync(new FilePickerSaveOptions()
+////                {
+////                    Title = "Save file",
+////                    FileTypeChoices = fileTypes,
+////                    SuggestedStartLocation = lastSelectedDirectory,
+////                    SuggestedFileName = "FileName",
+////                    DefaultExtension = fileTypes?.Any() == true ? "txt" : null,
+////                    ShowOverwritePrompt = false
+////                });
+
+////                if (file is not null && file.CanOpenWrite)
+////                {
+////                    // Sync disposal of StreamWriter is not supported on WASM
+////#if NET6_0_OR_GREATER
+////                    await using var stream = await file.OpenWriteAsync();
+////                    await using var reader = new System.IO.StreamWriter(stream);
+////#else
+////                    using var stream = await file.OpenWriteAsync();
+////                    using var reader = new System.IO.StreamWriter(stream);
+////#endif
+////                    await reader.WriteLineAsync(openedFileContent.Text);
+
+////                    lastSelectedDirectory = await file.GetParentAsync();
+////                }
+
+////                await SetPickerResult(file is null ? null : new [] {file});
+////            };
+////            this.Get<Button>("OpenFolderPicker").Click += async delegate
+////            {
+////                var folders = await GetStorageProvider().OpenFolderPickerAsync(new FolderPickerOpenOptions()
+////                {
+////                    Title = "Folder file",
+////                    SuggestedStartLocation = lastSelectedDirectory,
+////                    AllowMultiple = openMultiple.IsChecked == true
+////                });
+
+////                await SetPickerResult(folders);
+
+////                lastSelectedDirectory = folders.FirstOrDefault();
+////            };
+////            this.Get<Button>("OpenFileFromBookmark").Click += async delegate
+////            {
+////                var file = bookmarkContainer.Text is not null
+////                    ? await GetStorageProvider().OpenFileBookmarkAsync(bookmarkContainer.Text)
+////                    : null;
+
+////                await SetPickerResult(file is null ? null : new[] { file });
+////            };
+////            this.Get<Button>("OpenFolderFromBookmark").Click += async delegate
+////            {
+////                var folder = bookmarkContainer.Text is not null
+////                    ? await GetStorageProvider().OpenFolderBookmarkAsync(bookmarkContainer.Text)
+////                    : null;
+
+////                await SetPickerResult(folder is null ? null : new[] { folder });
                 
-                lastSelectedDirectory = folder;
-            };
-
-            async Task SetPickerResult(IReadOnlyCollection<IStorageItem>? items)
-            {
-                items ??= Array.Empty<IStorageItem>();
-                bookmarkContainer.Text = items.FirstOrDefault(f => f.CanBookmark) is { } f ? await f.SaveBookmarkAsync() : "Can't bookmark";
-                var mappedResults = new List<string>();
-
-                if (items.FirstOrDefault() is IStorageItem item)
-                {
-                    var resultText = item is IStorageFile ? "File:" : "Folder:";
-                    resultText += Environment.NewLine;
-
-                    var props = await item.GetBasicPropertiesAsync();
-                    resultText += @$"Size: {props.Size}
-DateCreated: {props.DateCreated}
-DateModified: {props.DateModified}
-CanBookmark: {item.CanBookmark}
-";
-                    if (item is IStorageFile file)
-                    {
-                        resultText += @$"
-CanOpenRead: {file.CanOpenRead}
-CanOpenWrite: {file.CanOpenWrite}
-Content:
-";
-                        if (file.CanOpenRead)
-                        {
-#if NET6_0_OR_GREATER
-                            await using var stream = await file.OpenReadAsync();
-#else
-                            using var stream = await file.OpenReadAsync();
-#endif
-                            using var reader = new System.IO.StreamReader(stream);
-
-                            // 4GB file test, shouldn't load more than 10000 chars into a memory.
-                            const int length = 10000;
-                            var buffer = ArrayPool<char>.Shared.Rent(length);
-                            try
-                            {
-                                var charsRead = await reader.ReadAsync(buffer, 0, length);
-                                resultText += new string(buffer, 0, charsRead);
-                            }
-                            finally
-                            {
-                                ArrayPool<char>.Shared.Return(buffer);
-                            }
-                        }
-                    }
-
-                    openedFileContent.Text = resultText;
-
-                    lastSelectedDirectory = await item.GetParentAsync();
-                    if (lastSelectedDirectory is not null)
-                    {
-                        mappedResults.Add(FullPathOrName(lastSelectedDirectory));
-                    }
-
-                    foreach (var selectedItem in items)
-                    {
-                        mappedResults.Add("+> " + FullPathOrName(selectedItem));
-                        if (selectedItem is IStorageFolder folder)
-                        {
-                            foreach (var innerItems in await folder.GetItemsAsync())
-                            {
-                                mappedResults.Add("++> " + FullPathOrName(innerItems));
-                            }
-                        }
-                    }
-                }
-
-                results.Items = mappedResults;
-                resultsVisible.IsVisible = mappedResults.Any();
-            }
+////                lastSelectedDirectory = folder;
+////            };
+
+////            async Task SetPickerResult(IReadOnlyCollection<IStorageItem>? items)
+////            {
+////                items ??= Array.Empty<IStorageItem>();
+////                bookmarkContainer.Text = items.FirstOrDefault(f => f.CanBookmark) is { } f ? await f.SaveBookmarkAsync() : "Can't bookmark";
+////                var mappedResults = new List<string>();
+
+////                if (items.FirstOrDefault() is IStorageItem item)
+////                {
+////                    var resultText = item is IStorageFile ? "File:" : "Folder:";
+////                    resultText += Environment.NewLine;
+
+////                    var props = await item.GetBasicPropertiesAsync();
+////                    resultText += @$"Size: {props.Size}
+////DateCreated: {props.DateCreated}
+////DateModified: {props.DateModified}
+////CanBookmark: {item.CanBookmark}
+////";
+////                    if (item is IStorageFile file)
+////                    {
+////                        resultText += @$"
+////CanOpenRead: {file.CanOpenRead}
+////CanOpenWrite: {file.CanOpenWrite}
+////Content:
+////";
+////                        if (file.CanOpenRead)
+////                        {
+////#if NET6_0_OR_GREATER
+////                            await using var stream = await file.OpenReadAsync();
+////#else
+////                            using var stream = await file.OpenReadAsync();
+////#endif
+////                            using var reader = new System.IO.StreamReader(stream);
+
+////                            // 4GB file test, shouldn't load more than 10000 chars into a memory.
+////                            const int length = 10000;
+////                            var buffer = ArrayPool<char>.Shared.Rent(length);
+////                            try
+////                            {
+////                                var charsRead = await reader.ReadAsync(buffer, 0, length);
+////                                resultText += new string(buffer, 0, charsRead);
+////                            }
+////                            finally
+////                            {
+////                                ArrayPool<char>.Shared.Return(buffer);
+////                            }
+////                        }
+////                    }
+
+////                    openedFileContent.Text = resultText;
+
+////                    lastSelectedDirectory = await item.GetParentAsync();
+////                    if (lastSelectedDirectory is not null)
+////                    {
+////                        mappedResults.Add(FullPathOrName(lastSelectedDirectory));
+////                    }
+
+////                    foreach (var selectedItem in items)
+////                    {
+////                        mappedResults.Add("+> " + FullPathOrName(selectedItem));
+////                        if (selectedItem is IStorageFolder folder)
+////                        {
+////                            foreach (var innerItems in await folder.GetItemsAsync())
+////                            {
+////                                mappedResults.Add("++> " + FullPathOrName(innerItems));
+////                            }
+////                        }
+////                    }
+////                }
+
+////                results.Items = mappedResults;
+////                resultsVisible.IsVisible = mappedResults.Any();
+////            }
         }
 
         protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)

+ 1 - 3
samples/SampleControls/HamburgerMenu/HamburgerMenu.xaml

@@ -168,9 +168,7 @@
                               HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
                               VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}">
                   <ItemsPresenter Name="PART_ItemsPresenter"
-                                  HorizontalAlignment="Stretch"
-                                  ItemTemplate="{TemplateBinding ItemTemplate}"
-                                  Items="{TemplateBinding Items}">
+                                  HorizontalAlignment="Stretch">
                     <ItemsPresenter.ItemsPanel>
                       <ItemsPanelTemplate>
                         <StackPanel x:Name="HamburgerItemsPanel"

+ 1 - 4
src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml

@@ -98,11 +98,8 @@
                         IsScrollChainingEnabled="{TemplateBinding (ScrollViewer.IsScrollChainingEnabled)}"
                         AllowAutoHide="{TemplateBinding (ScrollViewer.AllowAutoHide)}">
             <ItemsPresenter Name="PART_ItemsPresenter"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}"
-                            ItemTemplate="{TemplateBinding ItemTemplate}"
-                            Margin="{TemplateBinding Padding}"
-                            VirtualizationMode="{TemplateBinding VirtualizationMode}" />
+                            Margin="{TemplateBinding Padding}"/>
           </ScrollViewer>
         </Border>
       </ControlTemplate>

+ 1 - 4
src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml

@@ -98,11 +98,8 @@
                         IsScrollChainingEnabled="{TemplateBinding (ScrollViewer.IsScrollChainingEnabled)}"
                         AllowAutoHide="{TemplateBinding (ScrollViewer.AllowAutoHide)}">
             <ItemsPresenter Name="PART_ItemsPresenter"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}"
-                            ItemTemplate="{TemplateBinding ItemTemplate}"
-                            Margin="{TemplateBinding Padding}"
-                            VirtualizationMode="{TemplateBinding VirtualizationMode}" />
+                            Margin="{TemplateBinding Padding}"/>
           </ScrollViewer>
         </Border>
       </ControlTemplate>

+ 1 - 1
src/Avalonia.Controls/ComboBox.cs

@@ -57,7 +57,7 @@ namespace Avalonia.Controls
         /// Defines the <see cref="VirtualizationMode"/> property.
         /// </summary>
         public static readonly StyledProperty<ItemVirtualizationMode> VirtualizationModeProperty =
-            ItemsPresenter.VirtualizationModeProperty.AddOwner<ComboBox>();
+            VirtualizingStackPanel.VirtualizationModeProperty.AddOwner<ComboBox>();
 
         /// <summary>
         /// Defines the <see cref="PlaceholderText"/> property.

+ 0 - 78
src/Avalonia.Controls/IVirtualizingPanel.cs

@@ -7,83 +7,5 @@ namespace Avalonia.Controls
     /// </summary>
     public interface IVirtualizingPanel
     {
-        /// <summary>
-        /// Gets the children of the panel.
-        /// </summary>
-        Controls Children { get; }
-
-        /// <summary>
-        /// Gets or sets the controller for the virtualizing panel.
-        /// </summary>
-        /// <remarks>
-        /// A virtualizing controller is responsible for maintaining the controls in the virtualizing
-        /// panel. This property will be set by the controller when virtualization is initialized.
-        /// Note that this property may remain null if the panel is added to a control that does
-        /// not act as a virtualizing controller.
-        /// </remarks>
-        IVirtualizingController? Controller { get; set; }
-
-        /// <summary>
-        /// Gets a value indicating whether the panel is full.
-        /// </summary>
-        /// <remarks>
-        /// This property should return false until enough children are added to fill the space
-        /// passed into the last measure or arrange in the direction of scroll. It should be
-        /// updated immediately after a child is added or removed.
-        /// </remarks>
-        bool IsFull { get; }
-
-        /// <summary>
-        /// Gets the number of items that can be removed while keeping the panel full.
-        /// </summary>
-        /// <remarks>
-        /// This property should return the number of children that are completely out of the
-        /// panel's current bounds in the direction of scroll. It should be updated after an
-        /// arrange.
-        /// </remarks>
-        int OverflowCount { get; }
-
-        /// <summary>
-        /// Gets the direction of scroll.
-        /// </summary>
-        Orientation ScrollDirection { get; }
-
-        /// <summary>
-        /// Gets the average size of the materialized items in the direction of scroll.
-        /// </summary>
-        double AverageItemSize { get; }
-
-        /// <summary>
-        /// Gets or sets a size in pixels by which the content is overflowing the panel, in the
-        /// direction of scroll.
-        /// </summary>
-        /// <remarks>
-        /// This may be non-zero even when <see cref="OverflowCount"/> is zero if the last item
-        /// overflows the panel bounds.
-        /// </remarks>
-        double PixelOverflow { get; }
-
-        /// <summary>
-        /// Gets or sets the current pixel offset of the items in the direction of scroll.
-        /// </summary>
-        double PixelOffset { get; set; }
-
-        /// <summary>
-        /// Gets or sets the current scroll offset in the cross axis.
-        /// </summary>
-        double CrossAxisOffset { get; set; }
-
-        /// <summary>
-        /// Invalidates the measure of the control and forces a call to 
-        /// <see cref="IVirtualizingController.UpdateControls"/> on the next measure.
-        /// </summary>
-        /// <remarks>
-        /// The implementation for this method should call
-        /// <see cref="Layoutable.InvalidateMeasure"/> and also ensure that the next call to
-        /// <see cref="Layoutable.Measure(Size)"/> calls
-        /// <see cref="IVirtualizingController.UpdateControls"/> on the next measure even if
-        /// the available size hasn't changed.
-        /// </remarks>
-        void ForceInvalidateMeasure();
     }
 }

+ 2 - 10
src/Avalonia.Controls/ItemsControl.cs

@@ -174,7 +174,7 @@ namespace Avalonia.Controls
         /// <summary>
         /// Gets the items presenter control.
         /// </summary>
-        public IItemsPresenter? Presenter
+        public ItemsPresenter? Presenter
         {
             get;
             protected set;
@@ -189,7 +189,7 @@ namespace Avalonia.Controls
         }
 
         /// <inheritdoc/>
-        void IItemsPresenterHost.RegisterItemsPresenter(IItemsPresenter presenter)
+        void IItemsPresenterHost.RegisterItemsPresenter(ItemsPresenter presenter)
         {
             if (Presenter is IChildIndexProvider oldInnerProvider)
             {
@@ -408,12 +408,6 @@ namespace Avalonia.Controls
             UpdateItemCount();
             RemoveControlItemsFromLogicalChildren(oldValue);
             AddControlItemsToLogicalChildren(newValue);
-
-            if (Presenter != null)
-            {
-                Presenter.Items = newValue;
-            }
-
             SubscribeToItems(newValue);
         }
 
@@ -437,8 +431,6 @@ namespace Avalonia.Controls
                     RemoveControlItemsFromLogicalChildren(e.OldItems);
                     break;
             }
-
-            Presenter?.ItemsChanged(e);
         }
 
         /// <summary>

+ 1 - 1
src/Avalonia.Controls/ListBox.cs

@@ -51,7 +51,7 @@ namespace Avalonia.Controls
         /// Defines the <see cref="VirtualizationMode"/> property.
         /// </summary>
         public static readonly StyledProperty<ItemVirtualizationMode> VirtualizationModeProperty =
-            ItemsPresenter.VirtualizationModeProperty.AddOwner<ListBox>();
+            VirtualizingStackPanel.VirtualizationModeProperty.AddOwner<ListBox>();
 
         private IScrollable? _scroll;
 

+ 172 - 172
src/Avalonia.Controls/Presenters/CarouselPresenter.cs

@@ -12,7 +12,7 @@ namespace Avalonia.Controls.Presenters
     /// <summary>
     /// Displays pages inside an <see cref="ItemsControl"/>.
     /// </summary>
-    public class CarouselPresenter : ItemsPresenterBase
+    public class CarouselPresenter : ItemsPresenter
     {
         /// <summary>
         /// Defines the <see cref="IsVirtualized"/> property.
@@ -43,8 +43,8 @@ namespace Avalonia.Controls.Presenters
         /// </summary>
         static CarouselPresenter()
         {
-            IsVirtualizedProperty.Changed.AddClassHandler<CarouselPresenter>((x, e) => x.IsVirtualizedChanged(e));
-            SelectedIndexProperty.Changed.AddClassHandler<CarouselPresenter>((x, e) => x.SelectedIndexChanged(e));
+            ////IsVirtualizedProperty.Changed.AddClassHandler<CarouselPresenter>((x, e) => x.IsVirtualizedChanged(e));
+            ////SelectedIndexProperty.Changed.AddClassHandler<CarouselPresenter>((x, e) => x.SelectedIndexChanged(e));
         }
 
         /// <summary>
@@ -71,14 +71,14 @@ namespace Avalonia.Controls.Presenters
 
             set
             {
-                var old = SelectedIndex;
-                var effective = (value >= 0 && value < Items?.Cast<object>().Count()) ? value : -1;
+                ////var old = SelectedIndex;
+                ////var effective = (value >= 0 && value < Items?.Cast<object>().Count()) ? value : -1;
 
-                if (old != effective)
-                {
-                    _selectedIndex = effective;
-                    RaisePropertyChanged(SelectedIndexProperty, old, effective, BindingPriority.LocalValue);
-                }
+                ////if (old != effective)
+                ////{
+                ////    _selectedIndex = effective;
+                ////    RaisePropertyChanged(SelectedIndexProperty, old, effective, BindingPriority.LocalValue);
+                ////}
             }
         }
 
@@ -92,185 +92,185 @@ namespace Avalonia.Controls.Presenters
         }
 
         /// <inheritdoc/>
-        protected override void ItemsChanged(NotifyCollectionChangedEventArgs e)
-        {
-            if (!IsVirtualized)
-            {
-                base.ItemsChanged(e);
+        ////protected override void ItemsChanged(NotifyCollectionChangedEventArgs e)
+        ////{
+        ////    if (!IsVirtualized)
+        ////    {
+        ////        base.ItemsChanged(e);
 
-                if (Items == null || SelectedIndex >= Items.Count())
-                {
-                    SelectedIndex = Items.Count() - 1;
-                }
+        ////        if (Items == null || SelectedIndex >= Items.Count())
+        ////        {
+        ////            SelectedIndex = Items.Count() - 1;
+        ////        }
 
-                foreach (var c in ItemContainerGenerator.Containers)
-                {
-                    c.ContainerControl.IsVisible = c.Index == SelectedIndex;
-                }
-            }
-            else if (SelectedIndex != -1 && Panel != null)
-            {
-                switch (e.Action)
-                {
-                    case NotifyCollectionChangedAction.Add:
-                        if (e.NewStartingIndex > SelectedIndex)
-                        {
-                            return;
-                        }
-                        break;
-                    case NotifyCollectionChangedAction.Remove:
-                        if (e.OldStartingIndex > SelectedIndex)
-                        {
-                            return;
-                        }
-                        break;
-                    case NotifyCollectionChangedAction.Replace:
-                        if (e.OldStartingIndex > SelectedIndex ||
-                            e.OldStartingIndex + e.OldItems!.Count - 1 < SelectedIndex)
-                        {
-                            return;
-                        }
-                        break;
-                    case NotifyCollectionChangedAction.Move:
-                        if (e.OldStartingIndex > SelectedIndex &&
-                            e.NewStartingIndex > SelectedIndex)
-                        {
-                            return;
-                        }
-                        break;
-                }
+        ////        foreach (var c in ItemContainerGenerator.Containers)
+        ////        {
+        ////            c.ContainerControl.IsVisible = c.Index == SelectedIndex;
+        ////        }
+        ////    }
+        ////    else if (SelectedIndex != -1 && Panel != null)
+        ////    {
+        ////        switch (e.Action)
+        ////        {
+        ////            case NotifyCollectionChangedAction.Add:
+        ////                if (e.NewStartingIndex > SelectedIndex)
+        ////                {
+        ////                    return;
+        ////                }
+        ////                break;
+        ////            case NotifyCollectionChangedAction.Remove:
+        ////                if (e.OldStartingIndex > SelectedIndex)
+        ////                {
+        ////                    return;
+        ////                }
+        ////                break;
+        ////            case NotifyCollectionChangedAction.Replace:
+        ////                if (e.OldStartingIndex > SelectedIndex ||
+        ////                    e.OldStartingIndex + e.OldItems!.Count - 1 < SelectedIndex)
+        ////                {
+        ////                    return;
+        ////                }
+        ////                break;
+        ////            case NotifyCollectionChangedAction.Move:
+        ////                if (e.OldStartingIndex > SelectedIndex &&
+        ////                    e.NewStartingIndex > SelectedIndex)
+        ////                {
+        ////                    return;
+        ////                }
+        ////                break;
+        ////        }
 
-                if (Items == null || SelectedIndex >= Items.Count())
-                {
-                    SelectedIndex = Items.Count() - 1;
-                }
+        ////        if (Items == null || SelectedIndex >= Items.Count())
+        ////        {
+        ////            SelectedIndex = Items.Count() - 1;
+        ////        }
 
-                Panel.Children.Clear();
-                ItemContainerGenerator.Clear();
+        ////        Panel.Children.Clear();
+        ////        ItemContainerGenerator.Clear();
 
-                if (SelectedIndex != -1)
-                {
-                    GetOrCreateContainer(SelectedIndex);
-                }
-            }
-        }
+        ////        if (SelectedIndex != -1)
+        ////        {
+        ////            GetOrCreateContainer(SelectedIndex);
+        ////        }
+        ////    }
+        ////}
 
-        protected override void PanelCreated(Panel panel)
-        {
-            ItemsChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
-        }
+        ////protected override void PanelCreated(Panel panel)
+        ////{
+        ////    ItemsChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+        ////}
 
-        /// <summary>
-        /// Moves to the selected page, animating if a <see cref="PageTransition"/> is set.
-        /// </summary>
-        /// <param name="fromIndex">The index of the old page.</param>
-        /// <param name="toIndex">The index of the new page.</param>
-        /// <returns>A task tracking the animation.</returns>
-        private async Task MoveToPage(int fromIndex, int toIndex)
-        {
-            if (fromIndex != toIndex)
-            {
-                var generator = ItemContainerGenerator;
-                Control? from = null;
-                Control? to = null;
+        /////// <summary>
+        /////// Moves to the selected page, animating if a <see cref="PageTransition"/> is set.
+        /////// </summary>
+        /////// <param name="fromIndex">The index of the old page.</param>
+        /////// <param name="toIndex">The index of the new page.</param>
+        /////// <returns>A task tracking the animation.</returns>
+        ////private async Task MoveToPage(int fromIndex, int toIndex)
+        ////{
+        ////    if (fromIndex != toIndex)
+        ////    {
+        ////        var generator = ItemContainerGenerator;
+        ////        Control? from = null;
+        ////        Control? to = null;
 
-                if (fromIndex != -1)
-                {
-                    from = generator.ContainerFromIndex(fromIndex);
-                }
+        ////        if (fromIndex != -1)
+        ////        {
+        ////            from = generator.ContainerFromIndex(fromIndex);
+        ////        }
 
-                if (toIndex != -1)
-                {
-                    to = GetOrCreateContainer(toIndex);
-                }
+        ////        if (toIndex != -1)
+        ////        {
+        ////            to = GetOrCreateContainer(toIndex);
+        ////        }
 
-                if (PageTransition != null && (from != null || to != null))
-                {
-                    await PageTransition.Start((Visual?)from, (Visual?)to, fromIndex < toIndex, default);
-                }
-                else if (to != null)
-                {
-                    to.IsVisible = true;
-                }
+        ////        if (PageTransition != null && (from != null || to != null))
+        ////        {
+        ////            await PageTransition.Start((Visual?)from, (Visual?)to, fromIndex < toIndex, default);
+        ////        }
+        ////        else if (to != null)
+        ////        {
+        ////            to.IsVisible = true;
+        ////        }
 
-                if (from != null)
-                {
-                    if (IsVirtualized)
-                    {
-                        Panel!.Children.Remove(from);
-                        generator.Dematerialize(fromIndex, 1);
-                    }
-                    else
-                    {
-                        from.IsVisible = false;
-                    }
-                }
-            }
-        }
+        ////        if (from != null)
+        ////        {
+        ////            if (IsVirtualized)
+        ////            {
+        ////                Panel!.Children.Remove(from);
+        ////                generator.Dematerialize(fromIndex, 1);
+        ////            }
+        ////            else
+        ////            {
+        ////                from.IsVisible = false;
+        ////            }
+        ////        }
+        ////    }
+        ////}
 
-        private Control? GetOrCreateContainer(int index)
-        {
-            var container = ItemContainerGenerator.ContainerFromIndex(index);
+        ////private Control? GetOrCreateContainer(int index)
+        ////{
+        ////    var container = ItemContainerGenerator.ContainerFromIndex(index);
 
-            if (container == null && IsVirtualized)
-            {
-                var item = Items!.Cast<object>().ElementAt(index);
-                var materialized = ItemContainerGenerator.Materialize(index, item);
-                Panel!.Children.Add(materialized.ContainerControl);
-                container = materialized.ContainerControl;
-            }
+        ////    if (container == null && IsVirtualized)
+        ////    {
+        ////        var item = Items!.Cast<object>().ElementAt(index);
+        ////        var materialized = ItemContainerGenerator.Materialize(index, item);
+        ////        Panel!.Children.Add(materialized.ContainerControl);
+        ////        container = materialized.ContainerControl;
+        ////    }
 
-            return container;
-        }
+        ////    return container;
+        ////}
 
-        /// <summary>
-        /// Called when the <see cref="IsVirtualized"/> property changes.
-        /// </summary>
-        /// <param name="e">The event args.</param>
-        private void IsVirtualizedChanged(AvaloniaPropertyChangedEventArgs e)
-        {
-            if (Panel != null)
-            {
-                ItemsChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
-            }
-        }
+        /////// <summary>
+        /////// Called when the <see cref="IsVirtualized"/> property changes.
+        /////// </summary>
+        /////// <param name="e">The event args.</param>
+        ////private void IsVirtualizedChanged(AvaloniaPropertyChangedEventArgs e)
+        ////{
+        ////    if (Panel != null)
+        ////    {
+        ////        ItemsChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+        ////    }
+        ////}
 
-        /// <summary>
-        /// Called when the <see cref="SelectedIndex"/> property changes.
-        /// </summary>
-        /// <param name="e">The event args.</param>
-        private async void SelectedIndexChanged(AvaloniaPropertyChangedEventArgs e)
-        {
-            if (Panel != null)
-            {
-                if (_currentTransition == null)
-                {
-                    int fromIndex = (int)e.OldValue!;
-                    int toIndex = (int)e.NewValue!;
+        /////// <summary>
+        /////// Called when the <see cref="SelectedIndex"/> property changes.
+        /////// </summary>
+        /////// <param name="e">The event args.</param>
+        ////private async void SelectedIndexChanged(AvaloniaPropertyChangedEventArgs e)
+        ////{
+        ////    if (Panel != null)
+        ////    {
+        ////        if (_currentTransition == null)
+        ////        {
+        ////            int fromIndex = (int)e.OldValue!;
+        ////            int toIndex = (int)e.NewValue!;
 
-                    for (;;)
-                    {
-                        _currentTransition = MoveToPage(fromIndex, toIndex);
-                        await _currentTransition;
+        ////            for (;;)
+        ////            {
+        ////                _currentTransition = MoveToPage(fromIndex, toIndex);
+        ////                await _currentTransition;
 
-                        if (_queuedTransitionIndex != -1)
-                        {
-                            fromIndex = toIndex;
-                            toIndex = _queuedTransitionIndex;
-                            _queuedTransitionIndex = -1;
-                        }
-                        else
-                        {
-                            _currentTransition = null;
-                            break;
-                        }
-                    }
-                }
-                else
-                {
-                    _queuedTransitionIndex = (int)e.NewValue!;
-                }
-            }
-        }
+        ////                if (_queuedTransitionIndex != -1)
+        ////                {
+        ////                    fromIndex = toIndex;
+        ////                    toIndex = _queuedTransitionIndex;
+        ////                    _queuedTransitionIndex = -1;
+        ////                }
+        ////                else
+        ////                {
+        ////                    _currentTransition = null;
+        ////                    break;
+        ////                }
+        ////            }
+        ////        }
+        ////        else
+        ////        {
+        ////            _queuedTransitionIndex = (int)e.NewValue!;
+        ////        }
+        ////    }
+        ////}
     }
 }

+ 0 - 18
src/Avalonia.Controls/Presenters/IItemsPresenter.cs

@@ -1,18 +0,0 @@
-using System.Collections;
-using System.Collections.Specialized;
-using Avalonia.Metadata;
-
-namespace Avalonia.Controls.Presenters
-{
-    [NotClientImplementable]
-    public interface IItemsPresenter : IPresenter
-    {
-        IEnumerable? Items { get; set; }
-
-        Panel? Panel { get; }
-
-        void ItemsChanged(NotifyCollectionChangedEventArgs e);
-
-        void ScrollIntoView(int index);
-    }
-}

+ 2 - 2
src/Avalonia.Controls/Presenters/IItemsPresenterHost.cs

@@ -18,9 +18,9 @@ namespace Avalonia.Controls.Presenters
     public interface IItemsPresenterHost
     {
         /// <summary>
-        /// Registers an <see cref="IItemsPresenter"/> with a host control.
+        /// Registers an <see cref="ItemsPresenter"/> with a host control.
         /// </summary>
         /// <param name="presenter">The items presenter.</param>
-        void RegisterItemsPresenter(IItemsPresenter presenter);
+        void RegisterItemsPresenter(ItemsPresenter presenter);
     }
 }

+ 0 - 125
src/Avalonia.Controls/Presenters/ItemContainerSync.cs

@@ -1,125 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using Avalonia.Controls.Generators;
-using Avalonia.Controls.Utils;
-
-namespace Avalonia.Controls.Presenters
-{
-    internal static class ItemContainerSync
-    {
-        public static void ItemsChanged(
-            ItemsPresenterBase owner,
-            IEnumerable? items,
-            NotifyCollectionChangedEventArgs e)
-        {
-            var generator = owner.ItemContainerGenerator;
-            var panel = owner.Panel;
-
-            if (panel == null)
-            {
-                return;
-            }
-
-            void Add()
-            {
-                if (e.NewStartingIndex + e.NewItems!.Count < items!.Count())
-                {
-                    generator.InsertSpace(e.NewStartingIndex, e.NewItems.Count);
-                }
-
-                AddContainers(owner, e.NewStartingIndex, e.NewItems);
-            }
-
-            void Remove()
-            {
-                RemoveContainers(panel, generator.RemoveRange(e.OldStartingIndex, e.OldItems!.Count));
-            }
-
-            switch (e.Action)
-            {
-                case NotifyCollectionChangedAction.Add:
-                    Add();
-                    break;
-
-                case NotifyCollectionChangedAction.Remove:
-                    Remove();
-                    break;
-
-                case NotifyCollectionChangedAction.Replace:
-                    RemoveContainers(panel, generator.Dematerialize(e.OldStartingIndex, e.OldItems!.Count));
-                    var containers = AddContainers(owner, e.NewStartingIndex, e.NewItems!);
-
-                    var i = e.NewStartingIndex;
-
-                    foreach (var container in containers)
-                    {
-                        panel.Children[i++] = container.ContainerControl;
-                    }
-
-                    break;
-
-                case NotifyCollectionChangedAction.Move:
-                    Remove();
-                    Add();
-                    break;
-
-                case NotifyCollectionChangedAction.Reset:
-                    RemoveContainers(panel, generator.Clear());
-
-                    if (items != null)
-                    {
-                        AddContainers(owner, 0, items);
-                    }
-
-                    break;
-            }
-        }
-
-        private static IList<ItemContainerInfo> AddContainers(
-            ItemsPresenterBase owner,
-            int index,
-            IEnumerable items)
-        {
-            var generator = owner.ItemContainerGenerator;
-            var result = new List<ItemContainerInfo>();
-            var panel = owner.Panel;
-
-            foreach (var item in items)
-            {
-                var i = generator.Materialize(index++, item);
-
-                if (i.ContainerControl != null)
-                {
-                    if (i.Index < panel!.Children.Count)
-                    {
-                        // TODO: This will insert at the wrong place when there are null items.
-                        panel.Children.Insert(i.Index, i.ContainerControl);
-                    }
-                    else
-                    {
-                        panel.Children.Add(i.ContainerControl);
-                    }
-                }
-
-                result.Add(i);
-            }
-
-            return result;
-        }
-
-        private static void RemoveContainers(
-            Panel panel,
-            IEnumerable<ItemContainerInfo> items)
-        {
-            foreach (var i in items)
-            {
-                if (i.ContainerControl != null)
-                {
-                    panel.Children.Remove(i.ContainerControl);
-                }
-            }
-        }
-    }
-}

+ 0 - 303
src/Avalonia.Controls/Presenters/ItemVirtualizer.cs

@@ -1,303 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Specialized;
-using System.Reactive.Linq;
-using Avalonia.Controls.Primitives;
-using Avalonia.Controls.Utils;
-using Avalonia.Input;
-using Avalonia.Layout;
-using Avalonia.VisualTree;
-
-namespace Avalonia.Controls.Presenters
-{
-    /// <summary>
-    /// Base class for classes which handle virtualization for an <see cref="ItemsPresenter"/>.
-    /// </summary>
-    internal abstract class ItemVirtualizer : IVirtualizingController, IDisposable
-    {
-        private double _crossAxisOffset;
-        private IDisposable? _subscriptions;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ItemVirtualizer"/> class.
-        /// </summary>
-        /// <param name="owner"></param>
-        public ItemVirtualizer(ItemsPresenter owner)
-        {
-            Owner = owner;
-            Items = owner.Items;
-            ItemCount = owner.Items.Count();
-
-            var panel = VirtualizingPanel;
-
-            if (panel != null)
-            {
-                _subscriptions = ((AvaloniaObject)panel).GetObservable(Panel.BoundsProperty)
-                    .Skip(1)
-                    .Subscribe(_ => InvalidateScroll());
-            }
-        }
-
-        /// <summary>
-        /// Gets the <see cref="ItemsPresenter"/> which owns the virtualizer.
-        /// </summary>
-        public ItemsPresenter Owner { get; }
-
-        /// <summary>
-        /// Gets the <see cref="IVirtualizingPanel"/> which will host the items.
-        /// </summary>
-        public IVirtualizingPanel? VirtualizingPanel => Owner.Panel as IVirtualizingPanel;
-
-        /// <summary>
-        /// Gets the items to display.
-        /// </summary>
-        public IEnumerable? Items { get; private set; }
-
-        /// <summary>
-        /// Gets the number of items in <see cref="Items"/>.
-        /// </summary>
-        public int ItemCount { get; private set; }
-
-        /// <summary>
-        /// Gets or sets the index of the first item displayed in the panel.
-        /// </summary>
-        public int FirstIndex { get; protected set; }
-
-        /// <summary>
-        /// Gets or sets the index of the first item beyond those displayed in the panel.
-        /// </summary>
-        public int NextIndex { get; protected set; }
-
-        /// <summary>
-        /// Gets a value indicating whether the items should be scroll horizontally or vertically.
-        /// </summary>
-        public bool Vertical => VirtualizingPanel?.ScrollDirection == Orientation.Vertical;
-
-        /// <summary>
-        /// Gets a value indicating whether logical scrolling is enabled.
-        /// </summary>
-        public abstract bool IsLogicalScrollEnabled { get; }
-
-        /// <summary>
-        /// Gets the value of the scroll extent.
-        /// </summary>
-        public abstract double ExtentValue { get; }
-
-        /// <summary>
-        /// Gets or sets the value of the current scroll offset.
-        /// </summary>
-        public abstract double OffsetValue { get; set; }
-
-        /// <summary>
-        /// Gets the value of the scrollable viewport.
-        /// </summary>
-        public abstract double ViewportValue { get; }
-
-        /// <summary>
-        /// Gets the <see cref="ExtentValue"/> as a <see cref="Size"/>.
-        /// </summary>
-        public Size Extent
-        {
-            get
-            {
-                if (IsLogicalScrollEnabled && Owner.Panel is Panel panel)
-                {
-                    return Vertical ?
-                        new Size(panel.DesiredSize.Width, ExtentValue) :
-                        new Size(ExtentValue, panel.DesiredSize.Height);
-                }
-
-                return default;
-            }
-        }
-
-        /// <summary>
-        /// Gets the <see cref="ViewportValue"/> as a <see cref="Size"/>.
-        /// </summary>
-        public Size Viewport
-        {
-            get
-            {
-                if (IsLogicalScrollEnabled && Owner.Panel is Panel panel)
-                {
-                    return Vertical ?
-                        new Size(panel.Bounds.Width, ViewportValue) :
-                        new Size(ViewportValue, panel.Bounds.Height);
-                }
-
-                return default;
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets the <see cref="OffsetValue"/> as a <see cref="Vector"/>.
-        /// </summary>
-        public Vector Offset
-        {
-            get
-            {
-                if (IsLogicalScrollEnabled)
-                {
-                    return Vertical ? new Vector(_crossAxisOffset, OffsetValue) : new Vector(OffsetValue, _crossAxisOffset);
-                }
-
-                return default;
-            }
-
-            set
-            {
-                if (!IsLogicalScrollEnabled)
-                {
-                    throw new NotSupportedException("Logical scrolling disabled.");
-                }
-
-                var oldCrossAxisOffset = _crossAxisOffset;
-
-                if (Vertical)
-                {
-                    OffsetValue = value.Y;
-                    _crossAxisOffset = value.X;
-                }
-                else
-                {
-                    OffsetValue = value.X;
-                    _crossAxisOffset = value.Y;
-                }
-
-                if (_crossAxisOffset != oldCrossAxisOffset)
-                {
-                    Owner.InvalidateArrange();
-                }
-            }
-        }
-        
-        /// <summary>
-        /// Creates an <see cref="ItemVirtualizer"/> based on an item presenter's 
-        /// <see cref="ItemVirtualizationMode"/>.
-        /// </summary>
-        /// <param name="owner">The items presenter.</param>
-        /// <returns>An <see cref="ItemVirtualizer"/>.</returns>
-        public static ItemVirtualizer? Create(ItemsPresenter owner)
-        {
-            if (owner.Panel == null)
-            {
-                return null;
-            }
-
-            var virtualizingPanel = owner.Panel as IVirtualizingPanel;
-            var scrollContentPresenter = owner.Parent as IScrollable;
-            ItemVirtualizer? result = null;
-
-            if (virtualizingPanel != null && scrollContentPresenter is object)
-            {
-                switch (owner.VirtualizationMode)
-                {
-                    case ItemVirtualizationMode.Simple:
-                        result = new ItemVirtualizerSimple(owner);
-                        break;
-                }
-            }
-
-            if (result == null)
-            {
-                result = new ItemVirtualizerNone(owner);
-            }
-
-            if (virtualizingPanel != null)
-            {
-                virtualizingPanel.Controller = result;
-            }
-
-            return result;
-        }
-
-        /// <summary>
-        /// Carries out a measure for the related <see cref="ItemsPresenter"/>.
-        /// </summary>
-        /// <param name="availableSize">The size available to the control.</param>
-        /// <returns>The desired size for the control.</returns>
-        public virtual Size MeasureOverride(Size availableSize)
-        {
-            Owner.Panel!.Measure(availableSize);
-            return Owner.Panel.DesiredSize;
-        }
-
-        /// <summary>
-        /// Carries out an arrange for the related <see cref="ItemsPresenter"/>.
-        /// </summary>
-        /// <param name="finalSize">The size available to the control.</param>
-        /// <returns>The actual size used.</returns>
-        public virtual Size ArrangeOverride(Size finalSize)
-        {
-            if (VirtualizingPanel != null)
-            {
-                VirtualizingPanel.CrossAxisOffset = _crossAxisOffset;
-                Owner.Panel!.Arrange(new Rect(finalSize));
-            }
-            else
-            {
-                var origin = Vertical ? new Point(-_crossAxisOffset, 0) : new Point(0, _crossAxisOffset);
-                Owner.Panel!.Arrange(new Rect(origin, finalSize));
-            }
-
-            return finalSize;
-        }
-
-        /// <inheritdoc/>
-        public virtual void UpdateControls()
-        {
-        }
-
-        /// <summary>
-        /// Gets the next control in the specified direction.
-        /// </summary>
-        /// <param name="direction">The movement direction.</param>
-        /// <param name="from">The control from which movement begins.</param>
-        /// <returns>The control.</returns>
-        public virtual Control? GetControlInDirection(NavigationDirection direction, Control? from)
-        {
-            return null;
-        }
-
-        /// <summary>
-        /// Called when the items for the presenter change, either because 
-        /// <see cref="ItemsPresenterBase.Items"/> has been set, the items collection has been
-        /// modified, or the panel has been created.
-        /// </summary>
-        /// <param name="items">The items.</param>
-        /// <param name="e">A description of the change.</param>
-        public virtual void ItemsChanged(IEnumerable? items, NotifyCollectionChangedEventArgs e)
-        {
-            Items = items;
-            ItemCount = items?.Count() ?? 0;
-        }
-
-        /// <summary>
-        /// Scrolls the specified item into view.
-        /// </summary>
-        /// <param name="index">The index of the item.</param>
-        public virtual void ScrollIntoView(int index)
-        {
-        }
-
-        /// <inheritdoc/>
-        public virtual void Dispose()
-        {
-            _subscriptions?.Dispose();
-            _subscriptions = null;
-
-            if (VirtualizingPanel != null)
-            {
-                VirtualizingPanel.Controller = null;
-                VirtualizingPanel.Children.Clear();
-            }
-
-            Owner.ItemContainerGenerator.Clear();
-        }
-
-        /// <summary>
-        /// Invalidates the current scroll.
-        /// </summary>
-        protected void InvalidateScroll() => ((ILogicalScrollable)Owner).RaiseScrollInvalidated(EventArgs.Empty);
-    }
-}

+ 0 - 106
src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs

@@ -1,106 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using Avalonia.Controls.Generators;
-using Avalonia.Controls.Utils;
-
-namespace Avalonia.Controls.Presenters
-{
-    /// <summary>
-    /// Represents an item virtualizer for an <see cref="ItemsPresenter"/> that doesn't actually
-    /// virtualize items - it just creates a container for every item.
-    /// </summary>
-    internal class ItemVirtualizerNone : ItemVirtualizer
-    {
-        public ItemVirtualizerNone(ItemsPresenter owner)
-            : base(owner)
-        {
-            if (Items != null && owner.Panel != null)
-            {
-                AddContainers(0, Items);
-            }
-        }
-
-        /// <inheritdoc/>
-        public override bool IsLogicalScrollEnabled => false;
-
-        /// <summary>
-        /// This property should never be accessed because <see cref="IsLogicalScrollEnabled"/> is
-        /// false.
-        /// </summary>
-        public override double ExtentValue
-        {
-            get { throw new NotSupportedException(); }
-        }
-
-        /// <summary>
-        /// This property should never be accessed because <see cref="IsLogicalScrollEnabled"/> is
-        /// false.
-        /// </summary>
-        public override double OffsetValue
-        {
-            get { throw new NotSupportedException(); }
-            set { throw new NotSupportedException(); }
-        }
-
-        /// <summary>
-        /// This property should never be accessed because <see cref="IsLogicalScrollEnabled"/> is
-        /// false.
-        /// </summary>
-        public override double ViewportValue
-        {
-            get { throw new NotSupportedException(); }
-        }
-
-        /// <inheritdoc/>
-        public override void ItemsChanged(IEnumerable? items, NotifyCollectionChangedEventArgs e)
-        {
-            base.ItemsChanged(items, e);
-            ItemContainerSync.ItemsChanged(Owner, items, e);
-            Owner.InvalidateMeasure();
-        }
-
-        /// <summary>
-        /// Scrolls the specified item into view.
-        /// </summary>
-        /// <param name="index">The index of the item.</param>
-        public override void ScrollIntoView(int index)
-        {
-            if (index != -1)
-            {
-                var container = Owner.ItemContainerGenerator.ContainerFromIndex(index);
-                container?.BringIntoView();
-            }
-        }
-
-        private IList<ItemContainerInfo> AddContainers(int index, IEnumerable items)
-        {
-            var generator = Owner.ItemContainerGenerator;
-            var result = new List<ItemContainerInfo>();
-            var panel = Owner.Panel;
-
-            foreach (var item in items)
-            {
-                var i = generator.Materialize(index++, item);
-
-                if (i.ContainerControl != null)
-                {
-                    if (i.Index < panel!.Children.Count)
-                    {
-                        // TODO: This will insert at the wrong place when there are null items.
-                        panel.Children.Insert(i.Index, i.ContainerControl);
-                    }
-                    else
-                    {
-                        panel.Children.Add(i.ContainerControl);
-                    }
-                }
-
-                result.Add(i);
-            }
-
-            return result;
-        }
-    }
-}

+ 0 - 606
src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs

@@ -1,606 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Specialized;
-using System.Linq;
-using Avalonia.Controls.Primitives;
-using Avalonia.Controls.Utils;
-using Avalonia.Input;
-using Avalonia.Layout;
-using Avalonia.Utilities;
-using Avalonia.VisualTree;
-
-namespace Avalonia.Controls.Presenters
-{
-    /// <summary>
-    /// Handles virtualization in an <see cref="ItemsPresenter"/> for
-    /// <see cref="ItemVirtualizationMode.Simple"/>.
-    /// </summary>
-    internal class ItemVirtualizerSimple : ItemVirtualizer
-    {
-        private int _anchor;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ItemVirtualizerSimple"/> class.
-        /// </summary>
-        /// <param name="owner"></param>
-        public ItemVirtualizerSimple(ItemsPresenter owner)
-            : base(owner)
-        {
-            // Don't need to add children here as UpdateControls should be called by the panel
-            // measure/arrange.
-        }
-
-        /// <inheritdoc/>
-        public override bool IsLogicalScrollEnabled => true;
-
-        /// <inheritdoc/>
-        public override double ExtentValue => ItemCount;
-
-        /// <inheritdoc/>
-        public override double OffsetValue
-        {
-            get
-            {
-                var offset = VirtualizingPanel.PixelOffset > 0 ? 1 : 0;
-                return FirstIndex + offset;
-            }
-
-            set
-            {
-                var panel = VirtualizingPanel;
-                var offset = VirtualizingPanel.PixelOffset > 0 ? 1 : 0;
-                var delta = (int)(value - (FirstIndex + offset));
-
-                if (delta != 0)
-                {
-                    var newLastIndex = (NextIndex - 1) + delta;
-
-                    if (newLastIndex < ItemCount)
-                    {
-                        if (panel.PixelOffset > 0)
-                        {
-                            panel.PixelOffset = 0;
-                            delta += 1;
-                        }
-
-                        if (delta != 0)
-                        {
-                            RecycleContainersForMove(delta);
-                        }
-                    }
-                    else
-                    {
-                        // We're moving to a partially obscured item at the end of the list so
-                        // offset the panel by the height of the first item.
-                        var firstIndex = ItemCount - panel.Children.Count;
-                        RecycleContainersForMove(firstIndex - FirstIndex);
-
-                        double pixelOffset;
-                        var child = panel.Children[0];
-
-                        if (child.IsArrangeValid)
-                        {
-                            pixelOffset = VirtualizingPanel.ScrollDirection == Orientation.Vertical ?
-                                                    child.Bounds.Height :
-                                                    child.Bounds.Width;
-                        }
-                        else
-                        {
-                            pixelOffset = VirtualizingPanel.ScrollDirection == Orientation.Vertical ?
-                                                    child.DesiredSize.Height :
-                                                    child.DesiredSize.Width;
-                        }
-
-                        panel.PixelOffset = pixelOffset;
-                    }
-                }
-            }
-        }
-
-        /// <inheritdoc/>
-        public override double ViewportValue
-        {
-            get
-            {
-                // If we can't fit the last item in the panel fully, subtract 1 from the viewport.
-                var overflow = VirtualizingPanel.PixelOverflow > 0 ? 1 : 0;
-                return VirtualizingPanel.Children.Count - overflow;
-            }
-        }
-
-        public new IVirtualizingPanel VirtualizingPanel => base.VirtualizingPanel!;
-
-        /// <inheritdoc/>
-        public override Size MeasureOverride(Size availableSize)
-        {
-            var scrollable = (ILogicalScrollable)Owner;
-            var visualRoot = Owner.GetVisualRoot();
-            var maxAvailableSize = (visualRoot as WindowBase)?.PlatformImpl?.MaxAutoSizeHint
-                 ?? (visualRoot as TopLevel)?.ClientSize;
-
-            // If infinity is passed as the available size and we're virtualized then we need to
-            // fill the available space, but to do that we *don't* want to materialize all our
-            // items! Take a look at the root of the tree for a MaxClientSize and use that as
-            // the available size.
-            if (VirtualizingPanel.ScrollDirection == Orientation.Vertical)
-            {
-                if (availableSize.Height == double.PositiveInfinity)
-                {
-                    if (maxAvailableSize.HasValue)
-                    {
-                        availableSize = availableSize.WithHeight(maxAvailableSize.Value.Height);
-                    }
-                }
-
-                if (scrollable.CanHorizontallyScroll)
-                {
-                    availableSize = availableSize.WithWidth(double.PositiveInfinity);
-                }
-            }
-            else
-            {
-                if (availableSize.Width == double.PositiveInfinity)
-                {
-                    if (maxAvailableSize.HasValue)
-                    {
-                        availableSize = availableSize.WithWidth(maxAvailableSize.Value.Width);
-                    }
-                }
-
-                if (scrollable.CanVerticallyScroll)
-                {
-                    availableSize = availableSize.WithHeight(double.PositiveInfinity);
-                }
-            }
-
-            Owner.Panel!.Measure(availableSize);
-            return Owner.Panel.DesiredSize;
-        }
-
-        /// <inheritdoc/>
-        public override void UpdateControls()
-        {
-            CreateAndRemoveContainers();
-            InvalidateScroll();
-        }
-
-        /// <inheritdoc/>
-        public override void ItemsChanged(IEnumerable? items, NotifyCollectionChangedEventArgs e)
-        {
-            base.ItemsChanged(items, e);
-
-            var panel = VirtualizingPanel;
-
-            if (items != null)
-            {
-                switch (e.Action)
-                {
-                    case NotifyCollectionChangedAction.Add:
-                        CreateAndRemoveContainers();
-
-                        if (e.NewStartingIndex < NextIndex)
-                        {
-                            RecycleContainers();
-                        }
-
-                        panel.ForceInvalidateMeasure();
-                        break;
-
-                    case NotifyCollectionChangedAction.Remove:
-                        if (e.OldStartingIndex < NextIndex ||
-                            panel.Children.Count > ItemCount)
-                        {
-                            RecycleContainersOnRemove();
-                        }
-
-                        panel.ForceInvalidateMeasure();
-                        break;
-
-                    case NotifyCollectionChangedAction.Move:
-                    case NotifyCollectionChangedAction.Replace:
-                        RecycleContainers();
-                        break;
-
-                    case NotifyCollectionChangedAction.Reset:
-                        RecycleContainersOnRemove();
-                        CreateAndRemoveContainers();
-                        panel.ForceInvalidateMeasure();
-                        break;
-                }
-            }
-            else
-            {
-                Owner.ItemContainerGenerator.Clear();
-                VirtualizingPanel.Children.Clear();
-                FirstIndex = NextIndex = 0;
-            }
-
-            // If we are scrolled to view a partially visible last item but controls were added
-            // then we need to return to a non-offset scroll position.
-            if (panel.PixelOffset != 0 && FirstIndex + panel.Children.Count < ItemCount)
-            {
-                panel.PixelOffset = 0;
-                RecycleContainersForMove(1);
-            }
-
-            InvalidateScroll();
-        }
-
-        public override Control? GetControlInDirection(NavigationDirection direction, Control? from)
-        {
-            var generator = Owner.ItemContainerGenerator;
-            var panel = VirtualizingPanel;
-            var itemIndex = generator.IndexFromContainer(from);
-            var vertical = VirtualizingPanel.ScrollDirection == Orientation.Vertical;
-
-            var newItemIndex = -1;
-
-            switch (direction)
-            {
-                case NavigationDirection.First:
-                    newItemIndex = 0;
-                    break;
-
-                case NavigationDirection.Last:
-                    newItemIndex = ItemCount - 1;
-                    break;
-
-                default:
-                    if (itemIndex == -1)
-                    {
-                        return null;
-                    }
-                    break;
-            }
-
-            switch (direction)
-            {
-                case NavigationDirection.Up:
-                    if (vertical)
-                    {
-                        newItemIndex = itemIndex - 1;
-                    }
-
-                    break;
-                case NavigationDirection.Down:
-                    if (vertical)
-                    {
-                        newItemIndex = itemIndex + 1;
-                    }
-
-                    break;
-
-                case NavigationDirection.Left:
-                    if (!vertical)
-                    {
-                        newItemIndex = itemIndex - 1;
-                    }
-                    break;
-
-                case NavigationDirection.Right:
-                    if (!vertical)
-                    {
-                        newItemIndex = itemIndex + 1;
-                    }
-                    break;
-
-                case NavigationDirection.PageUp:
-                    newItemIndex = Math.Max(0, itemIndex - (int)ViewportValue);
-                    break;
-
-                case NavigationDirection.PageDown:
-                    newItemIndex = Math.Min(ItemCount - 1, itemIndex + (int)ViewportValue);
-                    break;
-            }
-
-            return ScrollIntoViewCore(newItemIndex);
-        }
-
-        /// <inheritdoc/>
-        public override void ScrollIntoView(int index)
-        {
-            if (index != -1)
-            {
-                ScrollIntoViewCore(index);
-            }
-        }
-
-        /// <summary>
-        /// Creates and removes containers such that we have at most enough containers to fill
-        /// the panel.
-        /// </summary>
-        private void CreateAndRemoveContainers()
-        {
-            var generator = Owner.ItemContainerGenerator;
-            var panel = VirtualizingPanel;
-            var panelControl = (Control)panel;
-
-            if (!panel.IsFull && Items != null && panelControl.IsAttachedToVisualTree)
-            {
-                var index = NextIndex;
-                var step = 1;
-
-                while (!panel.IsFull && index >= 0)
-                {
-                    if (index >= ItemCount)
-                    {
-                        // We can fit more containers in the panel, but we're at the end of the
-                        // items. If we're scrolled to the top (FirstIndex == 0), then there are
-                        // no more items to create. Otherwise, go backwards adding containers to
-                        // the beginning of the panel.
-                        if (FirstIndex == 0)
-                        {
-                            break;
-                        }
-                        else
-                        {
-                            index = FirstIndex - 1;
-                            step = -1;
-                        }
-                    }
-
-                    var materialized = generator.Materialize(index, Items.ElementAt(index)!);
-
-                    if (step == 1)
-                    {
-                        panel.Children.Add(materialized.ContainerControl);
-                    }
-                    else
-                    {
-                        panel.Children.Insert(0, materialized.ContainerControl);
-                    }
-
-                    index += step;
-                }
-
-                if (step == 1)
-                {
-                    NextIndex = index;
-                }
-                else
-                {
-                    NextIndex = ItemCount;
-                    FirstIndex = index + 1;
-                }
-            }
-
-            if (panel.OverflowCount > 0)
-            {
-                if (_anchor <= FirstIndex)
-                {
-                    RemoveContainers(panel.OverflowCount);
-                }
-            }
-        }
-
-        /// <summary>
-        /// Updates the containers in the panel to make sure they are displaying the correct item
-        /// based on <see cref="ItemVirtualizer.FirstIndex"/>.
-        /// </summary>
-        /// <remarks>
-        /// This method requires that <see cref="ItemVirtualizer.FirstIndex"/> + the number of
-        /// materialized containers is not more than <see cref="ItemVirtualizer.ItemCount"/>.
-        /// </remarks>
-        private void RecycleContainers()
-        {
-            var panel = VirtualizingPanel;
-            var generator = Owner.ItemContainerGenerator;
-            var containers = generator.Containers.ToList();
-            var itemIndex = FirstIndex;
-
-            foreach (var container in containers)
-            {
-                var item = Items!.ElementAt(itemIndex)!;
-
-                if (!object.Equals(container.Item, item))
-                {
-                    if (!generator.TryRecycle(itemIndex, itemIndex, item))
-                    {
-                        throw new NotImplementedException();
-                    }
-                }
-
-                ++itemIndex;
-            }
-        }
-
-        /// <summary>
-        /// Recycles containers when a move occurs.
-        /// </summary>
-        /// <param name="delta">The delta of the move.</param>
-        /// <remarks>
-        /// If the move is less than a page, then this method moves the containers for the items
-        /// that are still visible to the correct place, and recycles and moves the others. For
-        /// example: if there are 20 items and 10 containers visible and the user scrolls 5
-        /// items down, then the bottom 5 containers will be moved to the top and the top 5 will
-        /// be moved to the bottom and recycled to display the newly visible item. Updates 
-        /// <see cref="ItemVirtualizer.FirstIndex"/> and <see cref="ItemVirtualizer.NextIndex"/>
-        /// with their new values.
-        /// </remarks>
-        private void RecycleContainersForMove(int delta)
-        {
-            var panel = VirtualizingPanel;
-            var generator = Owner.ItemContainerGenerator;
-
-            //validate delta it should never overflow last index or generate index < 0 
-            delta = MathUtilities.Clamp(delta, -FirstIndex, ItemCount - FirstIndex - panel.Children.Count);
-
-            var sign = delta < 0 ? -1 : 1;
-            var count = Math.Min(Math.Abs(delta), panel.Children.Count);
-            var move = count < panel.Children.Count;
-            var first = delta < 0 && move ? panel.Children.Count + delta : 0;
-
-            for (var i = 0; i < count; ++i)
-            {
-                var oldItemIndex = FirstIndex + first + i;
-                var newItemIndex = oldItemIndex + delta + ((panel.Children.Count - count) * sign);
-
-                var item = Items!.ElementAt(newItemIndex)!;
-
-                if (!generator.TryRecycle(oldItemIndex, newItemIndex, item))
-                {
-                    throw new NotImplementedException();
-                }
-            }
-
-            if (move)
-            {
-                if (delta > 0)
-                {
-                    panel.Children.MoveRange(first, count, panel.Children.Count);
-                }
-                else
-                {
-                    panel.Children.MoveRange(first, count, 0);
-                }
-            }
-
-            FirstIndex += delta;
-            NextIndex += delta;
-        }
-
-        /// <summary>
-        /// Recycles containers due to items being removed.
-        /// </summary>
-        private void RecycleContainersOnRemove()
-        {
-            var panel = VirtualizingPanel;
-
-            if (NextIndex <= ItemCount)
-            {
-                // Items have been removed but FirstIndex..NextIndex is still a valid range in the
-                // items, so just recycle the containers to adapt to the new state.
-                RecycleContainers();
-            }
-            else
-            {
-                // Items have been removed and now the range FirstIndex..NextIndex goes out of 
-                // the item bounds. Remove any excess containers, try to scroll up and then recycle
-                // the containers to make sure they point to the correct item.
-                var newFirstIndex = Math.Max(0, FirstIndex - (NextIndex - ItemCount));
-                var delta = newFirstIndex - FirstIndex;
-                var newNextIndex = NextIndex + delta;
-
-                if (newNextIndex > ItemCount)
-                {
-                    RemoveContainers(newNextIndex - ItemCount);
-                }
-
-                if (delta != 0)
-                {
-                    RecycleContainersForMove(delta);
-                }
-
-                RecycleContainers();
-            }
-        }
-
-        /// <summary>
-        /// Removes the specified number of containers from the end of the panel and updates
-        /// <see cref="ItemVirtualizer.NextIndex"/>.
-        /// </summary>
-        /// <param name="count">The number of containers to remove.</param>
-        private void RemoveContainers(int count)
-        {
-            var index = VirtualizingPanel.Children.Count - count;
-
-            VirtualizingPanel.Children.RemoveRange(index, count);
-            Owner.ItemContainerGenerator.Dematerialize(FirstIndex + index, count);
-            NextIndex -= count;
-        }
-
-        /// <summary>
-        /// Scrolls the item with the specified index into view.
-        /// </summary>
-        /// <param name="index">The item index.</param>
-        /// <returns>The container that was brought into view.</returns>
-        private Control? ScrollIntoViewCore(int index)
-        {
-            var panel = VirtualizingPanel;
-            var panelControl = (Control)panel;
-            var generator = Owner.ItemContainerGenerator;
-            var newOffset = -1.0;
-
-            //better not trigger any container generation/recycle while  or layout stuff
-            //before panel is attached/visible
-            if (!panelControl.IsAttachedToVisualTree)
-            {
-                return null;
-            }
-
-            if (!panelControl.IsMeasureValid && panelControl.PreviousMeasure.HasValue)
-            {
-                //before any kind of scrolling we need to make sure panel measure is valid
-                //or we risk get panel into not valid state
-                //we make a preemptive quick measure so scrolling is valid
-                panelControl.Measure(panelControl.PreviousMeasure.Value);
-            }
-
-            if (index >= 0 && index < ItemCount)
-            {
-                if (index <= FirstIndex)
-                {
-                    newOffset = index;
-                }
-                else if (index >= NextIndex)
-                {
-                    newOffset = index - Math.Ceiling(ViewportValue - 1);
-                }
-
-                if (newOffset != -1)
-                {
-                    OffsetValue = newOffset;
-                }
-
-                var container = generator.ContainerFromIndex(index);
-                var layoutManager = (Owner.GetVisualRoot() as ILayoutRoot)?.LayoutManager;
-
-                // We need to do a layout here because it's possible that the container we moved to
-                // is only partially visible due to differing item sizes. If the container is only 
-                // partially visible, scroll again. Don't do this if there's no layout manager:
-                // it means we're running a unit test.
-                if (container != null && layoutManager != null)
-                {
-                    _anchor = index;
-                    layoutManager.ExecuteLayoutPass();
-                    _anchor = -1;
-
-                    if (newOffset != -1 && newOffset != OffsetValue)
-                    {
-                        OffsetValue = newOffset;
-                    }
-                    
-                    if (panel.ScrollDirection == Orientation.Vertical)
-                    {
-                        if (container.Bounds.Y < panelControl.Bounds.Y || container.Bounds.Bottom > panelControl.Bounds.Bottom)
-                        {
-                            OffsetValue += 1;
-                        }
-                    }
-                    else
-                    {
-                        if (container.Bounds.X < panelControl.Bounds.X || container.Bounds.Right > panelControl.Bounds.Right)
-                        {
-                            OffsetValue += 1;
-                        }
-                    }
-                }
-
-                return container;
-            }
-
-            return null;
-        }
-
-        /// <summary>
-        /// Ensures an offset value is within the value range.
-        /// </summary>
-        /// <param name="value">The value.</param>
-        /// <returns>The coerced value.</returns>
-        private double CoerceOffset(double value)
-        {
-            var max = Math.Max(ExtentValue - ViewportValue, 0);
-            return MathUtilities.Clamp(value, 0, max);
-        }
-    }
-}

+ 48 - 139
src/Avalonia.Controls/Presenters/ItemsPresenter.cs

@@ -1,179 +1,88 @@
 using System;
+using System.Collections;
 using System.Collections.Specialized;
-using Avalonia.Controls.Primitives;
-using Avalonia.Input;
-using static Avalonia.Utilities.MathUtilities;
+using System.Diagnostics;
 
 namespace Avalonia.Controls.Presenters
 {
     /// <summary>
-    /// Displays items inside an <see cref="ItemsControl"/>.
+    /// Presents items inside an <see cref="Avalonia.Controls.ItemsControl"/>.
     /// </summary>
-    public class ItemsPresenter : ItemsPresenterBase, ILogicalScrollable
+    public class ItemsPresenter : Control
     {
         /// <summary>
-        /// Defines the <see cref="VirtualizationMode"/> property.
+        /// Defines the <see cref="ItemsPanel"/> property.
         /// </summary>
-        public static readonly StyledProperty<ItemVirtualizationMode> VirtualizationModeProperty =
-            AvaloniaProperty.Register<ItemsPresenter, ItemVirtualizationMode>(
-                nameof(VirtualizationMode),
-                defaultValue: ItemVirtualizationMode.None);
+        public static readonly StyledProperty<ITemplate<Panel>> ItemsPanelProperty =
+            ItemsControl.ItemsPanelProperty.AddOwner<ItemsPresenter>();
 
-        private bool _canHorizontallyScroll;
-        private bool _canVerticallyScroll;
-        private EventHandler? _scrollInvalidated;
+        private ItemsPresenterContainerGenerator? _generator;
 
         /// <summary>
-        /// Initializes static members of the <see cref="ItemsPresenter"/> class.
+        /// Gets or sets a template which creates the <see cref="Panel"/> used to display the items.
         /// </summary>
-        static ItemsPresenter()
+        public ITemplate<Panel> ItemsPanel
         {
-            KeyboardNavigation.TabNavigationProperty.OverrideDefaultValue(
-                typeof(ItemsPresenter),
-                KeyboardNavigationMode.Once);
-
-            VirtualizationModeProperty.Changed
-                .AddClassHandler<ItemsPresenter>((x, e) => x.VirtualizationModeChanged(e));
+            get => GetValue(ItemsPanelProperty);
+            set => SetValue(ItemsPanelProperty, value);
         }
 
         /// <summary>
-        /// Gets or sets the virtualization mode for the items.
+        /// Gets the panel used to display the items.
         /// </summary>
-        public ItemVirtualizationMode VirtualizationMode
-        {
-            get { return GetValue(VirtualizationModeProperty); }
-            set { SetValue(VirtualizationModeProperty, value); }
-        }
+        public Panel? Panel { get; private set; }
 
         /// <summary>
-        /// Gets or sets a value indicating whether the content can be scrolled horizontally.
+        /// Gets the owner <see cref="ItemsControl"/>.
         /// </summary>
-        bool ILogicalScrollable.CanHorizontallyScroll
-        {
-            get { return _canHorizontallyScroll; }
-            set
-            {
-                _canHorizontallyScroll = value;
-                InvalidateMeasure();
-            }
-        }
+        internal ItemsControl? ItemsControl { get; private set; }
 
-        /// <summary>
-        /// Gets or sets a value indicating whether the content can be scrolled horizontally.
-        /// </summary>
-        bool ILogicalScrollable.CanVerticallyScroll
+        public override sealed void ApplyTemplate()
         {
-            get { return _canVerticallyScroll; }
-            set
+            if (Panel is null)
             {
-                _canVerticallyScroll = value;
-                InvalidateMeasure();
+                Panel = ItemsPanel.Build();
+                Panel.SetValue(TemplatedParentProperty, TemplatedParent);
+                LogicalChildren.Add(Panel);
+                VisualChildren.Add(Panel);
+                CreateGeneratorIfSimplePanel();
             }
         }
-        /// <inheritdoc/>
-        bool ILogicalScrollable.IsLogicalScrollEnabled
-        {
-            get { return Virtualizer?.IsLogicalScrollEnabled ?? false; }
-        }
-
-        /// <inheritdoc/>
-        Size IScrollable.Extent => Virtualizer?.Extent ?? Size.Empty;
 
-        /// <inheritdoc/>
-        Vector IScrollable.Offset
+        protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
         {
-            get { return Virtualizer?.Offset ?? new Vector(); }
-            set
+            base.OnPropertyChanged(change);
+
+            if (change.Property == TemplatedParentProperty)
             {
-                if (Virtualizer != null)
+                _generator?.Dispose();
+                _generator = null;
+
+                if (change.NewValue is ItemsControl itemsControl)
                 {
-                    Virtualizer.Offset = CoerceOffset(value);
+                    ItemsControl = itemsControl;
+                    ((IItemsPresenterHost)itemsControl)?.RegisterItemsPresenter(this);
+                    CreateGeneratorIfSimplePanel();
                 }
             }
+            else if (change.Property == ItemsPanelProperty)
+            {
+                _generator?.Dispose();
+                _generator = null;
+                LogicalChildren.Clear();
+                VisualChildren.Clear();
+                Panel = null;
+                InvalidateMeasure();
+            }
         }
 
-        /// <inheritdoc/>
-        Size IScrollable.Viewport => Virtualizer?.Viewport ?? Bounds.Size;
-
-        /// <inheritdoc/>
-        event EventHandler? ILogicalScrollable.ScrollInvalidated
-        {
-            add => _scrollInvalidated += value;
-            remove => _scrollInvalidated -= value;
-        }
-
-        /// <inheritdoc/>
-        Size ILogicalScrollable.ScrollSize => new Size(ScrollViewer.DefaultSmallChange, 1);
-
-        /// <inheritdoc/>
-        Size ILogicalScrollable.PageScrollSize => Virtualizer?.Viewport ?? new Size(16, 16);
-
-        internal ItemVirtualizer? Virtualizer { get; private set; }
-
-        /// <inheritdoc/>
-        bool ILogicalScrollable.BringIntoView(Control target, Rect targetRect)
-        {
-            return false;
-        }
-
-        /// <inheritdoc/>
-        Control? ILogicalScrollable.GetControlInDirection(NavigationDirection direction, Control? from)
-        {
-            return Virtualizer?.GetControlInDirection(direction, from);
-        }
-
-        /// <inheritdoc/>
-        void ILogicalScrollable.RaiseScrollInvalidated(EventArgs e)
-        {
-            _scrollInvalidated?.Invoke(this, e);
-        }
-
-        public override void ScrollIntoView(int index)
-        {
-            Virtualizer?.ScrollIntoView(index);
-        }
-
-        /// <inheritdoc/>
-        protected override Size MeasureOverride(Size availableSize)
-        {
-            return Virtualizer?.MeasureOverride(availableSize) ?? Size.Empty;
-        }
-
-        protected override Size ArrangeOverride(Size finalSize)
-        {
-            return Virtualizer?.ArrangeOverride(finalSize) ?? Size.Empty;
-        }
-
-        /// <inheritdoc/>
-        protected override void PanelCreated(Panel panel)
-        {
-            Virtualizer?.Dispose();
-            Virtualizer = ItemVirtualizer.Create(this);
-            _scrollInvalidated?.Invoke(this, EventArgs.Empty);
-
-            KeyboardNavigation.SetTabNavigation(
-                (InputElement)panel,
-                KeyboardNavigation.GetTabNavigation(this));
-        }
-
-        protected override void ItemsChanged(NotifyCollectionChangedEventArgs e)
-        {
-            Virtualizer?.ItemsChanged(Items, e);
-        }
-
-        private Vector CoerceOffset(Vector value)
+        private void CreateGeneratorIfSimplePanel()
         {
-            var scrollable = (ILogicalScrollable)this;
-            var maxX = Math.Max(scrollable.Extent.Width - scrollable.Viewport.Width, 0);
-            var maxY = Math.Max(scrollable.Extent.Height - scrollable.Viewport.Height, 0);
-            return new Vector(Clamp(value.X, 0, maxX), Clamp(value.Y, 0, maxY));
-        }
+            if (ItemsControl is null || Panel is null || Panel is IVirtualizingPanel)
+                return;
 
-        private void VirtualizationModeChanged(AvaloniaPropertyChangedEventArgs e)
-        {
-            Virtualizer?.Dispose();
-            Virtualizer = ItemVirtualizer.Create(this);
-            _scrollInvalidated?.Invoke(this, EventArgs.Empty);
+            _generator?.Dispose();
+            _generator = new(this);
         }
     }
 }

+ 0 - 308
src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs

@@ -1,308 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Specialized;
-using Avalonia.Collections;
-using Avalonia.Controls.Generators;
-using Avalonia.Controls.Templates;
-using Avalonia.Controls.Utils;
-using Avalonia.Data;
-using Avalonia.LogicalTree;
-using Avalonia.Styling;
-
-namespace Avalonia.Controls.Presenters
-{
-    /// <summary>
-    /// Base class for controls that present items inside an <see cref="ItemsControl"/>.
-    /// </summary>
-    public abstract class ItemsPresenterBase : Control, IItemsPresenter, IChildIndexProvider
-    {
-        /// <summary>
-        /// Defines the <see cref="Items"/> property.
-        /// </summary>
-        public static readonly DirectProperty<ItemsPresenterBase, IEnumerable?> ItemsProperty =
-            ItemsControl.ItemsProperty.AddOwner<ItemsPresenterBase>(o => o.Items, (o, v) => o.Items = v);
-
-        /// <summary>
-        /// Defines the <see cref="ItemsPanel"/> property.
-        /// </summary>
-        public static readonly StyledProperty<ITemplate<Panel>> ItemsPanelProperty =
-            ItemsControl.ItemsPanelProperty.AddOwner<ItemsPresenterBase>();
-
-        /// <summary>
-        /// Defines the <see cref="ItemTemplate"/> property.
-        /// </summary>
-        public static readonly StyledProperty<IDataTemplate?> ItemTemplateProperty =
-            ItemsControl.ItemTemplateProperty.AddOwner<ItemsPresenterBase>();
-
-        /// <summary>
-        /// Defines the <see cref="DisplayMemberBinding" /> property
-        /// </summary>
-        public static readonly StyledProperty<IBinding?> DisplayMemberBindingProperty =
-            ItemsControl.DisplayMemberBindingProperty.AddOwner<ItemsPresenterBase>();
-        
-        private IEnumerable? _items;
-        private IDisposable? _itemsSubscription;
-        private bool _createdPanel;
-        private IItemContainerGenerator? _generator;
-        private EventHandler<ChildIndexChangedEventArgs>? _childIndexChanged;
-
-        /// <summary>
-        /// Initializes static members of the <see cref="ItemsPresenter"/> class.
-        /// </summary>
-        static ItemsPresenterBase()
-        {
-            TemplatedParentProperty.Changed.AddClassHandler<ItemsPresenterBase>((x,e) => x.TemplatedParentChanged(e));
-        }
-
-        /// <summary>
-        /// Gets or sets the items to be displayed.
-        /// </summary>
-        public IEnumerable? Items
-        {
-            get
-            {
-                return _items;
-            }
-
-            set
-            {
-                _itemsSubscription?.Dispose();
-                _itemsSubscription = null;
-
-                if (!IsHosted && _createdPanel && value is INotifyCollectionChanged incc)
-                {
-                    _itemsSubscription = incc.WeakSubscribe(ItemsCollectionChanged);
-                }
-
-                SetAndRaise(ItemsProperty, ref _items, value);
-
-                if (_createdPanel)
-                {
-                    ItemsChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets the item container generator.
-        /// </summary>
-        public IItemContainerGenerator ItemContainerGenerator
-        {
-            get
-            {
-                if (_generator == null)
-                {
-                    _generator = CreateItemContainerGenerator();
-                }
-
-                return _generator;
-            }
-
-            internal set
-            {
-                if (_generator != null)
-                {
-                    throw new InvalidOperationException("ItemContainerGenerator already created.");
-                }
-
-                _generator = value;
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets a template which creates the <see cref="Panel"/> used to display the items.
-        /// </summary>
-        public ITemplate<Panel> ItemsPanel
-        {
-            get { return GetValue(ItemsPanelProperty); }
-            set { SetValue(ItemsPanelProperty, value); }
-        }
-
-        /// <summary>
-        /// Gets or sets the data template used to display the items in the control.
-        /// </summary>
-        public IDataTemplate? ItemTemplate
-        {
-            get { return GetValue(ItemTemplateProperty); }
-            set { SetValue(ItemTemplateProperty, value); }
-        }
-
-        /// <summary>
-        /// Gets or sets the <see cref="IBinding"/> to use for binding to the display member of each item.
-        /// </summary>
-        public IBinding? DisplayMemberBinding
-        {
-            get { return GetValue(DisplayMemberBindingProperty); }
-            set { SetValue(DisplayMemberBindingProperty, value); }
-        }
-
-        /// <summary>
-        /// Gets the panel used to display the items.
-        /// </summary>
-        public Panel? Panel
-        {
-            get;
-            private set;
-        }
-
-        protected bool IsHosted => TemplatedParent is IItemsPresenterHost;
-
-        event EventHandler<ChildIndexChangedEventArgs>? IChildIndexProvider.ChildIndexChanged
-        {
-            add => _childIndexChanged += value;
-            remove => _childIndexChanged -= value;
-        }
-
-        /// <inheritdoc/>
-        public override sealed void ApplyTemplate()
-        {
-            if (!_createdPanel)
-            {
-                CreatePanel();
-            }
-        }
-
-        /// <inheritdoc/>
-        public virtual void ScrollIntoView(int index)
-        {
-        }
-
-        /// <inheritdoc/>
-        void IItemsPresenter.ItemsChanged(NotifyCollectionChangedEventArgs e)
-        {
-            if (Panel != null)
-            {
-                ItemsChanged(e);
-
-                _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty);
-            }
-        }
-
-        /// <summary>
-        /// Creates the <see cref="ItemContainerGenerator"/> for the control.
-        /// </summary>
-        /// <returns>
-        /// An <see cref="IItemContainerGenerator"/> or null.
-        /// </returns>
-        protected virtual IItemContainerGenerator CreateItemContainerGenerator()
-        {
-            var i = TemplatedParent as ItemsControl;
-            var result = i?.ItemContainerGenerator;
-
-            if (result == null)
-            {
-                result = new ItemContainerGenerator(this);
-                result.ItemTemplate = ItemTemplate;
-                result.DisplayMemberBinding = DisplayMemberBinding;
-            }
-
-            result.Materialized += ContainerActionHandler;
-            result.Dematerialized += ContainerActionHandler;
-            result.Recycled += ContainerActionHandler;
-
-            return result;
-        }
-
-        private void ContainerActionHandler(object? sender, ItemContainerEventArgs e)
-        {
-            for (var i = 0; i < e.Containers.Count; i++)
-            {
-                _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(e.Containers[i].ContainerControl));
-            }
-        }
-
-        /// <inheritdoc/>
-        protected override Size MeasureOverride(Size availableSize)
-        {
-            Panel!.Measure(availableSize);
-            return Panel.DesiredSize;
-        }
-
-        /// <inheritdoc/>
-        protected override Size ArrangeOverride(Size finalSize)
-        {
-            Panel!.Arrange(new Rect(finalSize));
-            return finalSize;
-        }
-
-        /// <summary>
-        /// Called when the <see cref="Panel"/> is created.
-        /// </summary>
-        /// <param name="panel">The panel.</param>
-        protected virtual void PanelCreated(Panel panel)
-        {
-        }
-
-        /// <summary>
-        /// Called when the items for the presenter change, either because <see cref="Items"/>
-        /// has been set, the items collection has been modified, or the panel has been created.
-        /// </summary>
-        /// <param name="e">A description of the change.</param>
-        /// <remarks>
-        /// The panel is guaranteed to be created when this method is called.
-        /// </remarks>
-        protected virtual void ItemsChanged(NotifyCollectionChangedEventArgs e)
-        {
-            ItemContainerSync.ItemsChanged(this, Items, e);
-        }
-
-        /// <summary>
-        /// Creates the <see cref="Panel"/> when <see cref="ApplyTemplate"/> is called for the first
-        /// time.
-        /// </summary>
-        private void CreatePanel()
-        {
-            Panel = ItemsPanel.Build();
-            Panel.SetValue(TemplatedParentProperty, TemplatedParent);
-
-            LogicalChildren.Clear();
-            VisualChildren.Clear();
-            LogicalChildren.Add(Panel);
-            VisualChildren.Add(Panel);
-
-            _createdPanel = true;
-
-            if (!IsHosted && _itemsSubscription == null && Items is INotifyCollectionChanged incc)
-            {
-                _itemsSubscription = incc.WeakSubscribe(ItemsCollectionChanged);
-            }
-
-            PanelCreated(Panel);
-        }
-
-        /// <summary>
-        /// Called when the <see cref="Items"/> collection changes.
-        /// </summary>
-        /// <param name="sender">The sender.</param>
-        /// <param name="e">The event args.</param>
-        private void ItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
-        {
-            if (_createdPanel)
-            {
-                ItemsChanged(e);
-            }
-        }
-
-        private void TemplatedParentChanged(AvaloniaPropertyChangedEventArgs e)
-        {
-            (e.NewValue as IItemsPresenterHost)?.RegisterItemsPresenter(this);
-        }
-
-        int IChildIndexProvider.GetChildIndex(ILogical child)
-        {
-            if (child is Control control && ItemContainerGenerator is { } generator)
-            {
-                var index = ItemContainerGenerator.IndexFromContainer(control);
-
-                return index;
-            }
-
-            return -1;
-        }
-
-        bool IChildIndexProvider.TryGetTotalCount(out int count)
-        {
-            return Items.TryGetCountFast(out count);
-        }
-    }
-}

+ 108 - 0
src/Avalonia.Controls/Presenters/ItemsPresenterContainerGenerator.cs

@@ -0,0 +1,108 @@
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Diagnostics;
+
+namespace Avalonia.Controls.Presenters
+{
+    /// <summary>
+    /// Generates containers for <see cref="ItemsPresenter"/>s that have non-virtualizing panels.
+    /// </summary>
+    internal class ItemsPresenterContainerGenerator : IDisposable
+    {
+        private static NotifyCollectionChangedEventArgs s_Reset = new(NotifyCollectionChangedAction.Reset);
+        private ItemsPresenter _presenter;
+
+        public ItemsPresenterContainerGenerator(ItemsPresenter presenter)
+        {
+            Debug.Assert(presenter.ItemsControl is not null);
+            Debug.Assert(presenter.Panel is not null or IVirtualizingPanel);
+            
+            _presenter = presenter;
+            _presenter.ItemsControl.PropertyChanged += OnItemsControlPropertyChanged;
+
+            if (_presenter.ItemsControl.Items is INotifyCollectionChanged incc)
+                incc.CollectionChanged += OnItemsChanged;
+
+            OnItemsChanged(null, s_Reset);
+        }
+
+        public void Dispose()
+        {
+            _presenter.ItemsControl!.PropertyChanged -= OnItemsControlPropertyChanged;
+
+            if (_presenter.ItemsControl.Items is INotifyCollectionChanged incc)
+                incc.CollectionChanged -= OnItemsChanged;
+
+            _presenter.Panel!.Children.Clear();
+        }
+
+        private void OnItemsControlPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
+        {
+            if (e.Property == ItemsControl.ItemsProperty)
+            {
+                if (e.OldValue is INotifyCollectionChanged inccOld)
+                    inccOld.CollectionChanged -= OnItemsChanged;
+                OnItemsChanged(null, s_Reset);
+                if (e.NewValue is INotifyCollectionChanged inccNew)
+                    inccNew.CollectionChanged += OnItemsChanged;
+            }
+        }
+
+        private void OnItemsChanged(object? sender, NotifyCollectionChangedEventArgs e)
+        {
+            if (_presenter.ItemsControl?.Items is null || _presenter.Panel is null)
+                return;
+
+            var generator = _presenter.ItemsControl.ItemContainerGenerator;
+            var panel = _presenter.Panel;
+
+            void Add(int index, IEnumerable items)
+            {
+                var i = index;
+
+                foreach (var item in items)
+                {
+                    var c = generator.Materialize(i, item);
+                    panel.Children.Insert(i++, c.ContainerControl);
+                }
+            }
+            
+            void Remove(int index, int count)
+            {
+                for (var i = 0; i < count; ++i)
+                    panel.Children.RemoveAt(i + index);
+            }
+
+            switch (e.Action)
+            {
+                case NotifyCollectionChangedAction.Add:
+                    generator.InsertSpace(e.NewStartingIndex, e.NewItems!.Count);
+                    Add(e.NewStartingIndex, e.NewItems!);
+                    break;
+                case NotifyCollectionChangedAction.Remove:
+                    generator.RemoveRange(e.OldStartingIndex, e.OldItems!.Count);
+                    Remove(e.OldStartingIndex, e.OldItems!.Count);
+                    break;
+                case NotifyCollectionChangedAction.Replace:
+                    generator.RemoveRange(e.OldStartingIndex, e.OldItems!.Count);
+                    Remove(e.OldStartingIndex, e.OldItems!.Count);
+                    generator.InsertSpace(e.NewStartingIndex, e.NewItems!.Count);
+                    Add(e.NewStartingIndex, e.NewItems!);
+                    break;
+                case NotifyCollectionChangedAction.Move:
+                    generator.RemoveRange(e.OldStartingIndex, e.OldItems!.Count);
+                    Remove(e.OldStartingIndex, e.OldItems!.Count);
+                    generator.InsertSpace(e.NewStartingIndex, e.NewItems!.Count);
+                    Add(e.NewStartingIndex, e.NewItems!);
+                    break;
+                case NotifyCollectionChangedAction.Reset:
+                    generator.Clear();
+                    panel.Children.Clear();
+                    if (_presenter.ItemsControl.Items is { } items)
+                        Add(0, items);
+                    break;
+            }
+        }
+    }
+}

+ 1 - 1
src/Avalonia.Controls/Primitives/SelectingItemsControl.cs

@@ -373,7 +373,7 @@ namespace Avalonia.Controls.Primitives
         /// Scrolls the specified item into view.
         /// </summary>
         /// <param name="index">The index of the item.</param>
-        public void ScrollIntoView(int index) => Presenter?.ScrollIntoView(index);
+        public void ScrollIntoView(int index) => throw new NotImplementedException(); ////Presenter?.ScrollIntoView(index);
 
         /// <summary>
         /// Scrolls the specified item into view.

+ 10 - 242
src/Avalonia.Controls/VirtualizingStackPanel.cs

@@ -1,252 +1,20 @@
 using System;
-using System.Collections.Specialized;
-using Avalonia.Controls.Primitives;
-using Avalonia.Input;
-using Avalonia.Layout;
 
 namespace Avalonia.Controls
 {
-    public class VirtualizingStackPanel : StackPanel, IVirtualizingPanel
+    public class VirtualizingStackPanel : StackPanel
     {
-        private Size _availableSpace;
-        private double _takenSpace;
-        private int _canBeRemoved;
-        private double _averageItemSize;
-        private int _averageCount;
-        private double _pixelOffset;
-        private double _crossAxisOffset;
-        private bool _forceRemeasure;
+        /// <summary>
+        /// Defines the <see cref="VirtualizationMode"/> property.
+        /// </summary>
+        public static readonly StyledProperty<ItemVirtualizationMode> VirtualizationModeProperty =
+            AvaloniaProperty.Register<VirtualizingStackPanel, ItemVirtualizationMode>(
+                nameof(VirtualizationMode));
 
-        bool IVirtualizingPanel.IsFull
+        public ItemVirtualizationMode VirtualizationMode
         {
-            get
-            {
-                return Orientation == Orientation.Horizontal ?
-                    _takenSpace >= _availableSpace.Width :
-                    _takenSpace >= _availableSpace.Height;
-            }
-        }
-
-        IVirtualizingController? IVirtualizingPanel.Controller { get; set; }
-        int IVirtualizingPanel.OverflowCount => _canBeRemoved;
-        Orientation IVirtualizingPanel.ScrollDirection => Orientation;
-        double IVirtualizingPanel.AverageItemSize => _averageItemSize;
-
-        double IVirtualizingPanel.PixelOverflow
-        {
-            get
-            {
-                var bounds = Orientation == Orientation.Horizontal ?
-                    _availableSpace.Width : _availableSpace.Height;
-                return Math.Max(0, _takenSpace - bounds);
-            }
-        }
-
-        double IVirtualizingPanel.PixelOffset
-        {
-            get { return _pixelOffset; }
-
-            set
-            {
-                if (_pixelOffset != value)
-                {
-                    _pixelOffset = value;
-                    InvalidateArrange();
-                }
-            }
-        }
-
-        double IVirtualizingPanel.CrossAxisOffset
-        {
-            get { return _crossAxisOffset; }
-
-            set
-            {
-                if (_crossAxisOffset != value)
-                {
-                    _crossAxisOffset = value;
-                    InvalidateArrange();
-                }
-            }
-        }
-
-        private IVirtualizingController? Controller => ((IVirtualizingPanel)this).Controller;
-
-        void IVirtualizingPanel.ForceInvalidateMeasure()
-        {
-            InvalidateMeasure();
-            _forceRemeasure = true;
-        }
-
-        protected override Size MeasureOverride(Size availableSize)
-        {
-            if (_forceRemeasure || availableSize != PreviousMeasure)
-            {
-                _forceRemeasure = false;
-                _availableSpace = availableSize;
-                Controller?.UpdateControls();
-            }
-
-            return base.MeasureOverride(availableSize);
-        }
-
-        protected override Size ArrangeOverride(Size finalSize)
-        {
-            _availableSpace = finalSize;
-            _canBeRemoved = 0;
-            _takenSpace = 0;
-            _averageItemSize = 0;
-            _averageCount = 0;
-            var result = base.ArrangeOverride(finalSize);
-            _takenSpace += _pixelOffset;
-            Controller?.UpdateControls();
-            return result;
-        }
-
-        protected override void ChildrenChanged(object? sender, NotifyCollectionChangedEventArgs e)
-        {
-            base.ChildrenChanged(sender, e);
-
-            switch (e.Action)
-            {
-                case NotifyCollectionChangedAction.Add:
-                    foreach (Control control in e.NewItems!)
-                    {
-                        UpdateAdd(control);
-                    }
-
-                    break;
-
-                case NotifyCollectionChangedAction.Remove:
-                    foreach (Control control in e.OldItems!)
-                    {
-                        UpdateRemove(control);
-                    }
-
-                    break;
-            }
-        }
-
-        protected override IInputElement? GetControlInDirection(NavigationDirection direction, Control? from)
-        {
-            var logicalScrollable = Parent as ILogicalScrollable;
-
-            if (logicalScrollable?.IsLogicalScrollEnabled == true)
-            {
-                return logicalScrollable.GetControlInDirection(direction, from);
-            }
-            else
-            {
-                return base.GetControlInDirection(direction, from);
-            }
-        }
-
-        internal override void ArrangeChild(
-            Control child,
-            Rect rect,
-            Size panelSize,
-            Orientation orientation)
-        {
-            if (orientation == Orientation.Vertical)
-            {
-                rect = new Rect(
-                    rect.X - _crossAxisOffset,
-                    rect.Y - _pixelOffset,
-                    rect.Width,
-                    rect.Height);
-                child.Arrange(rect);
-
-                if (rect.Y >= _availableSpace.Height)
-                {
-                    ++_canBeRemoved;
-                }
-
-                if (rect.Bottom >= _takenSpace)
-                {
-                    _takenSpace = rect.Bottom;
-                }
-
-                AddToAverageItemSize(rect.Height);
-            }
-            else
-            {
-                rect = new Rect(
-                    rect.X - _pixelOffset,
-                    rect.Y - _crossAxisOffset,
-                    rect.Width,
-                    rect.Height);
-                child.Arrange(rect);
-
-                if (rect.X >= _availableSpace.Width)
-                {
-                    ++_canBeRemoved;
-                }
-
-                if (rect.Right >= _takenSpace)
-                {
-                    _takenSpace = rect.Right;
-                }
-
-                AddToAverageItemSize(rect.Width);
-            }
-        }
-
-        private void UpdateAdd(Control child)
-        {
-            var bounds = Bounds;
-            var spacing = Spacing;
-
-            child.Measure(_availableSpace);
-            ++_averageCount;
-
-            if (Orientation == Orientation.Vertical)
-            {
-                var height = child.DesiredSize.Height;
-                _takenSpace += height + spacing;
-                AddToAverageItemSize(height);
-            }
-            else
-            {
-                var width = child.DesiredSize.Width;
-                _takenSpace += width + spacing;
-                AddToAverageItemSize(width);
-            }
-        }
-
-        private void UpdateRemove(Control child)
-        {
-            var bounds = Bounds;
-            var spacing = Spacing;
-
-            if (Orientation == Orientation.Vertical)
-            {
-                var height = child.DesiredSize.Height;
-                _takenSpace -= height + spacing;
-                RemoveFromAverageItemSize(height);
-            }
-            else
-            {
-                var width = child.DesiredSize.Width;
-                _takenSpace -= width + spacing;
-                RemoveFromAverageItemSize(width);
-            }
-
-            if (_canBeRemoved > 0)
-            {
-                --_canBeRemoved;
-            }
-        }
-
-        private void AddToAverageItemSize(double value)
-        {
-            ++_averageCount;
-            _averageItemSize += (value - _averageItemSize) / _averageCount;
-        }
-
-        private void RemoveFromAverageItemSize(double value)
-        {
-            _averageItemSize = ((_averageItemSize * _averageCount) - value) / (_averageCount - 1);
-            --_averageCount;
+            get => GetValue(VirtualizationModeProperty);
+            set => SetValue(VirtualizationModeProperty, value);
         }
     }
 }

+ 0 - 1
src/Avalonia.Themes.Fluent/Controls/Carousel.xaml

@@ -8,7 +8,6 @@
                 BorderThickness="{TemplateBinding BorderThickness}"
                 CornerRadius="{TemplateBinding CornerRadius}">
           <CarouselPresenter IsVirtualized="{TemplateBinding IsVirtualized}"
-                             Items="{TemplateBinding Items}"
                              ItemsPanel="{TemplateBinding ItemsPanel}"
                              Margin="{TemplateBinding Padding}"
                              SelectedIndex="{TemplateBinding SelectedIndex}"

+ 1 - 4
src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml

@@ -128,11 +128,8 @@
                 <ScrollViewer HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                               VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
                   <ItemsPresenter Name="PART_ItemsPresenter"
-                                  Items="{TemplateBinding Items}"
                                   Margin="{DynamicResource ComboBoxDropdownContentMargin}"
-                                  ItemsPanel="{TemplateBinding ItemsPanel}"
-                                  ItemTemplate="{TemplateBinding ItemTemplate}"
-                                  VirtualizationMode="{TemplateBinding VirtualizationMode}" />
+                                  ItemsPanel="{TemplateBinding ItemsPanel}" />
                 </ScrollViewer>
               </Border>
             </Popup>

+ 0 - 2
src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml

@@ -56,9 +56,7 @@
                 CornerRadius="{TemplateBinding CornerRadius}">
           <ScrollViewer Theme="{StaticResource FluentMenuScrollViewer}">
             <ItemsPresenter Name="PART_ItemsPresenter"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}"
-                            ItemTemplate="{TemplateBinding ItemTemplate}"
                             Margin="{DynamicResource MenuFlyoutScrollerMargin}"
                             KeyboardNavigation.TabNavigation="Continue"
                             Grid.IsSharedSizeScope="True" />

+ 1 - 3
src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml

@@ -9,9 +9,7 @@
                 CornerRadius="{TemplateBinding CornerRadius}"
                 Padding="{TemplateBinding Padding}">
           <ItemsPresenter Name="PART_ItemsPresenter"
-                          Items="{TemplateBinding Items}"
-                          ItemsPanel="{TemplateBinding ItemsPanel}"
-                          ItemTemplate="{TemplateBinding ItemTemplate}"/>
+                          ItemsPanel="{TemplateBinding ItemsPanel}"/>
         </Border>
       </ControlTemplate>
     </Setter>

+ 1 - 4
src/Avalonia.Themes.Fluent/Controls/ListBox.xaml

@@ -34,11 +34,8 @@
                         IsScrollChainingEnabled="{TemplateBinding (ScrollViewer.IsScrollChainingEnabled)}"
                         AllowAutoHide="{TemplateBinding (ScrollViewer.AllowAutoHide)}">
             <ItemsPresenter Name="PART_ItemsPresenter"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}"
-                            ItemTemplate="{TemplateBinding ItemTemplate}"
-                            Margin="{TemplateBinding Padding}"
-                            VirtualizationMode="{TemplateBinding VirtualizationMode}" />
+                            Margin="{TemplateBinding Padding}"/>
           </ScrollViewer>
         </Border>
       </ControlTemplate>

+ 1 - 4
src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml

@@ -273,11 +273,8 @@
           <Border Name="border" BoxShadow="inset -6 0 3 -3 #20000000" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
             <ScrollViewer Name="PART_ScrollViewer" HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}" VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}">
               <ItemsPresenter Name="PART_ItemsPresenter"
-                              Items="{TemplateBinding Items}"
                               ItemsPanel="{TemplateBinding ItemsPanel}"
-                              ItemTemplate="{TemplateBinding ItemTemplate}"
-                              Margin="{TemplateBinding Padding}"
-                              VirtualizationMode="{TemplateBinding VirtualizationMode}"/>
+                              Margin="{TemplateBinding Padding}"/>
             </ScrollViewer>
           </Border>
         </ControlTemplate>

+ 0 - 4
src/Avalonia.Themes.Fluent/Controls/Menu.xaml

@@ -48,9 +48,7 @@
                       CornerRadius="{DynamicResource OverlayCornerRadius}">
                 <ScrollViewer Theme="{StaticResource FluentMenuScrollViewer}">
                   <ItemsPresenter Name="PART_ItemsPresenter"
-                                  Items="{TemplateBinding Items}"
                                   ItemsPanel="{TemplateBinding ItemsPanel}"
-                                  ItemTemplate="{TemplateBinding ItemTemplate}"
                                   Margin="{DynamicResource MenuFlyoutScrollerMargin}"
                                   Grid.IsSharedSizeScope="True" />
                 </ScrollViewer>
@@ -101,9 +99,7 @@
                 HorizontalAlignment="Stretch"
                 Padding="{TemplateBinding Padding}">
           <ItemsPresenter Name="PART_ItemsPresenter"
-                          Items="{TemplateBinding Items}"
                           ItemsPanel="{TemplateBinding ItemsPanel}"
-                          ItemTemplate="{TemplateBinding ItemTemplate}"
                           VerticalAlignment="Stretch"
                           KeyboardNavigation.TabNavigation="Continue" />
         </Border>

+ 0 - 2
src/Avalonia.Themes.Fluent/Controls/MenuFlyoutPresenter.xaml

@@ -22,9 +22,7 @@
                         Theme="{StaticResource FluentMenuScrollViewer}"
                         VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
             <ItemsPresenter Name="PART_ItemsPresenter"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}"
-                            ItemTemplate="{TemplateBinding ItemTemplate}"
                             Margin="{DynamicResource MenuFlyoutScrollerMargin}"
                             KeyboardNavigation.TabNavigation="Continue"
                             Grid.IsSharedSizeScope="True" />

+ 0 - 2
src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml

@@ -131,9 +131,7 @@
                     CornerRadius="{DynamicResource OverlayCornerRadius}">
               <ScrollViewer Theme="{StaticResource FluentMenuScrollViewer}">
                 <ItemsPresenter Name="PART_ItemsPresenter"
-                                Items="{TemplateBinding Items}"
                                 ItemsPanel="{TemplateBinding ItemsPanel}"
-                                ItemTemplate="{TemplateBinding ItemTemplate}"
                                 Margin="{DynamicResource MenuFlyoutScrollerMargin}"
                                 Grid.IsSharedSizeScope="True" />
               </ScrollViewer>

+ 0 - 2
src/Avalonia.Themes.Fluent/Controls/TabControl.xaml

@@ -32,9 +32,7 @@
                 VerticalAlignment="{TemplateBinding VerticalAlignment}">
           <DockPanel>
             <ItemsPresenter Name="PART_ItemsPresenter"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}"
-                            ItemTemplate="{TemplateBinding ItemTemplate}"
                             DockPanel.Dock="{TemplateBinding TabStripPlacement}" />
             <ContentPresenter Name="PART_SelectedContentHost"
                               Margin="{TemplateBinding Padding}"

+ 1 - 3
src/Avalonia.Themes.Fluent/Controls/TabStrip.xaml

@@ -19,9 +19,7 @@
                 CornerRadius="{TemplateBinding CornerRadius}"
                 Padding="{TemplateBinding Padding}">
           <ItemsPresenter Name="PART_ItemsPresenter"
-                          Items="{TemplateBinding Items}"
-                          ItemsPanel="{TemplateBinding ItemsPanel}"
-                          ItemTemplate="{TemplateBinding ItemTemplate}" />
+                          ItemsPanel="{TemplateBinding ItemsPanel}" />
         </Border>
       </ControlTemplate>
     </Setter>

+ 0 - 1
src/Avalonia.Themes.Fluent/Controls/TreeView.xaml

@@ -32,7 +32,6 @@
                         IsScrollChainingEnabled="{TemplateBinding (ScrollViewer.IsScrollChainingEnabled)}"
                         AllowAutoHide="{TemplateBinding (ScrollViewer.AllowAutoHide)}">
             <ItemsPresenter Name="PART_ItemsPresenter"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}"
                             Margin="{TemplateBinding Padding}" />
           </ScrollViewer>

+ 0 - 1
src/Avalonia.Themes.Fluent/Controls/TreeViewItem.xaml

@@ -95,7 +95,6 @@
           </Border>
           <ItemsPresenter Name="PART_ItemsPresenter"
                           IsVisible="{TemplateBinding IsExpanded}"
-                          Items="{TemplateBinding Items}"
                           ItemsPanel="{TemplateBinding ItemsPanel}" />
         </StackPanel>
       </ControlTemplate>

+ 0 - 1
src/Avalonia.Themes.Simple/Controls/Carousel.xaml

@@ -10,7 +10,6 @@
                 CornerRadius="{TemplateBinding CornerRadius}">
           <CarouselPresenter Margin="{TemplateBinding Padding}"
                              IsVirtualized="{TemplateBinding IsVirtualized}"
-                             Items="{TemplateBinding Items}"
                              ItemsPanel="{TemplateBinding ItemsPanel}"
                              PageTransition="{TemplateBinding PageTransition}"
                              SelectedIndex="{TemplateBinding SelectedIndex}" />

+ 1 - 4
src/Avalonia.Themes.Simple/Controls/ComboBox.xaml

@@ -62,10 +62,7 @@
                 <ScrollViewer HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                               VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
                   <ItemsPresenter Name="PART_ItemsPresenter"
-                                  ItemTemplate="{TemplateBinding ItemTemplate}"
-                                  Items="{TemplateBinding Items}"
-                                  ItemsPanel="{TemplateBinding ItemsPanel}"
-                                  VirtualizationMode="{TemplateBinding VirtualizationMode}" />
+                                  ItemsPanel="{TemplateBinding ItemsPanel}" />
                 </ScrollViewer>
               </Border>
             </Popup>

+ 0 - 2
src/Avalonia.Themes.Simple/Controls/ContextMenu.xaml

@@ -17,8 +17,6 @@
                 CornerRadius="{TemplateBinding CornerRadius}">
           <ScrollViewer Theme="{StaticResource SimpleMenuScrollViewer}">
             <ItemsPresenter Name="PART_ItemsPresenter"
-                            ItemTemplate="{TemplateBinding ItemTemplate}"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}"
                             KeyboardNavigation.TabNavigation="Continue" />
           </ScrollViewer>

+ 0 - 2
src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml

@@ -10,8 +10,6 @@
                 BorderThickness="{TemplateBinding BorderThickness}"
                 CornerRadius="{TemplateBinding CornerRadius}">
           <ItemsPresenter Name="PART_ItemsPresenter"
-                          ItemTemplate="{TemplateBinding ItemTemplate}"
-                          Items="{TemplateBinding Items}"
                           ItemsPanel="{TemplateBinding ItemsPanel}" />
         </Border>
       </ControlTemplate>

+ 1 - 4
src/Avalonia.Themes.Simple/Controls/ListBox.xaml

@@ -23,10 +23,7 @@
                         VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}">
             <ItemsPresenter Name="PART_ItemsPresenter"
                             Margin="{TemplateBinding Padding}"
-                            ItemTemplate="{TemplateBinding ItemTemplate}"
-                            Items="{TemplateBinding Items}"
-                            ItemsPanel="{TemplateBinding ItemsPanel}"
-                            VirtualizationMode="{TemplateBinding VirtualizationMode}" />
+                            ItemsPanel="{TemplateBinding ItemsPanel}" />
           </ScrollViewer>
         </Border>
       </ControlTemplate>

+ 0 - 4
src/Avalonia.Themes.Simple/Controls/Menu.xaml

@@ -36,8 +36,6 @@
                   <ItemsPresenter Name="PART_ItemsPresenter"
                                   Margin="2"
                                   Grid.IsSharedSizeScope="True"
-                                  ItemTemplate="{TemplateBinding ItemTemplate}"
-                                  Items="{TemplateBinding Items}"
                                   ItemsPanel="{TemplateBinding ItemsPanel}" />
                 </ScrollViewer>
               </Border>
@@ -72,8 +70,6 @@
                 BorderThickness="{TemplateBinding BorderThickness}"
                 CornerRadius="{TemplateBinding CornerRadius}">
           <ItemsPresenter Name="PART_ItemsPresenter"
-                          ItemTemplate="{TemplateBinding ItemTemplate}"
-                          Items="{TemplateBinding Items}"
                           ItemsPanel="{TemplateBinding ItemsPanel}"
                           KeyboardNavigation.TabNavigation="Continue" />
         </Border>

+ 0 - 2
src/Avalonia.Themes.Simple/Controls/MenuFlyoutPresenter.xaml

@@ -20,8 +20,6 @@
             <ItemsPresenter Name="PART_ItemsPresenter"
                             Margin="{TemplateBinding Padding}"
                             Grid.IsSharedSizeScope="True"
-                            ItemTemplate="{TemplateBinding ItemTemplate}"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}"
                             KeyboardNavigation.TabNavigation="Continue" />
           </ScrollViewer>

+ 0 - 2
src/Avalonia.Themes.Simple/Controls/MenuItem.xaml

@@ -72,8 +72,6 @@
                   <ItemsPresenter Name="PART_ItemsPresenter"
                                   Margin="2"
                                   Grid.IsSharedSizeScope="True"
-                                  ItemTemplate="{TemplateBinding ItemTemplate}"
-                                  Items="{TemplateBinding Items}"
                                   ItemsPanel="{TemplateBinding ItemsPanel}" />
                 </ScrollViewer>
               </Border>

+ 0 - 2
src/Avalonia.Themes.Simple/Controls/TabControl.xaml

@@ -14,8 +14,6 @@
                 CornerRadius="{TemplateBinding CornerRadius}">
           <DockPanel>
             <ItemsPresenter Name="PART_ItemsPresenter"
-                            ItemTemplate="{TemplateBinding ItemTemplate}"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}" />
             <ContentPresenter Name="PART_SelectedContentHost"
                               Margin="{TemplateBinding Padding}"

+ 0 - 2
src/Avalonia.Themes.Simple/Controls/TabStrip.xaml

@@ -5,8 +5,6 @@
     <Setter Property="Template">
       <ControlTemplate>
         <ItemsPresenter Name="PART_ItemsPresenter"
-                        ItemTemplate="{TemplateBinding ItemTemplate}"
-                        Items="{TemplateBinding Items}"
                         ItemsPanel="{TemplateBinding ItemsPanel}" />
       </ControlTemplate>
     </Setter>

+ 0 - 1
src/Avalonia.Themes.Simple/Controls/TreeView.xaml

@@ -21,7 +21,6 @@
                         VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}">
             <ItemsPresenter Name="PART_ItemsPresenter"
                             Margin="{TemplateBinding Padding}"
-                            Items="{TemplateBinding Items}"
                             ItemsPanel="{TemplateBinding ItemsPanel}" />
           </ScrollViewer>
         </Border>

+ 0 - 1
src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml

@@ -63,7 +63,6 @@
           </Border>
           <ItemsPresenter Name="PART_ItemsPresenter"
                           IsVisible="{TemplateBinding IsExpanded}"
-                          Items="{TemplateBinding Items}"
                           ItemsPanel="{TemplateBinding ItemsPanel}" />
         </StackPanel>
       </ControlTemplate>

+ 0 - 1
tests/Avalonia.Controls.UnitTests/CarouselTests.cs

@@ -300,7 +300,6 @@ namespace Avalonia.Controls.UnitTests
             {
                 Name = "PART_ItemsPresenter",
                 [~CarouselPresenter.IsVirtualizedProperty] = control[~Carousel.IsVirtualizedProperty],
-                [~CarouselPresenter.ItemsProperty] = control[~Carousel.ItemsProperty],
                 [~CarouselPresenter.ItemsPanelProperty] = control[~Carousel.ItemsPanelProperty],
                 [~CarouselPresenter.SelectedIndexProperty] = control[~Carousel.SelectedIndexProperty],
                 [~CarouselPresenter.PageTransitionProperty] = control[~Carousel.PageTransitionProperty],

+ 0 - 1
tests/Avalonia.Controls.UnitTests/ComboBoxTests.cs

@@ -204,7 +204,6 @@ namespace Avalonia.Controls.UnitTests
                             Child = new ItemsPresenter
                             {
                                 Name = "PART_ItemsPresenter",
-                                [!ItemsPresenter.ItemsProperty] = parent[!ComboBox.ItemsProperty],
                             }.RegisterInNameScope(scope)
                         }.RegisterInNameScope(scope)
                     }

+ 1 - 3
tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs

@@ -544,7 +544,6 @@ namespace Avalonia.Controls.UnitTests
             var presenter = new ItemsPresenter
             {
                 [StyledElement.TemplatedParentProperty] = target,
-                [~ItemsPresenter.ItemsProperty] = target[~ItemsControl.ItemsProperty],
             };
 
             presenter.ApplyTemplate();
@@ -777,7 +776,6 @@ namespace Avalonia.Controls.UnitTests
                     Child = new ItemsPresenter
                     {
                         Name = "PART_ItemsPresenter",
-                        [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
                     }.RegisterInNameScope(scope)
                 };
             });
@@ -785,7 +783,7 @@ namespace Avalonia.Controls.UnitTests
 
         private class TestItemsControl : ItemsControl
         {
-            public new IItemsPresenter Presenter
+            public new ItemsPresenter Presenter
             {
                 get { return base.Presenter; }
                 set { base.Presenter = value; }

+ 26 - 26
tests/Avalonia.Controls.UnitTests/ListBoxTests.cs

@@ -1,3 +1,4 @@
+using System;
 using System.Collections.ObjectModel;
 using System.Linq;
 using System.Reactive.Subjects;
@@ -330,38 +331,39 @@ namespace Avalonia.Controls.UnitTests
         [Fact]
         public void ListBox_After_Scroll_IndexOutOfRangeException_Shouldnt_Be_Thrown()
         {
-            using (UnitTestApplication.Start(TestServices.StyledWindow))
-            {
-                var items = Enumerable.Range(0, 11).Select(x => $"{x}").ToArray();
+            throw new NotImplementedException();
+            ////using (UnitTestApplication.Start(TestServices.StyledWindow))
+            ////{
+            ////    var items = Enumerable.Range(0, 11).Select(x => $"{x}").ToArray();
 
-                var target = new ListBox
-                {
-                    Template = ListBoxTemplate(),
-                    Items = items,
-                    ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Height = 11 })
-                };
+            ////    var target = new ListBox
+            ////    {
+            ////        Template = ListBoxTemplate(),
+            ////        Items = items,
+            ////        ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Height = 11 })
+            ////    };
 
-                Prepare(target);
+            ////    Prepare(target);
 
-                var panel = target.Presenter.Panel as IVirtualizingPanel;
+            ////    var panel = target.Presenter.Panel as IVirtualizingPanel;
 
-                var listBoxItems = panel.Children.OfType<ListBoxItem>();
+            ////    var listBoxItems = panel.Children.OfType<ListBoxItem>();
 
-                //virtualization should have created exactly 10 items
-                Assert.Equal(10, listBoxItems.Count());
-                Assert.Equal("0", listBoxItems.First().DataContext);
-                Assert.Equal("9", listBoxItems.Last().DataContext);
+            ////    //virtualization should have created exactly 10 items
+            ////    Assert.Equal(10, listBoxItems.Count());
+            ////    Assert.Equal("0", listBoxItems.First().DataContext);
+            ////    Assert.Equal("9", listBoxItems.Last().DataContext);
 
-                //instead pixeloffset > 0 there could be pretty complex sequence for repro
-                //it involves add/remove/scroll to end multiple actions
-                //which i can't find so far :(, but this is the simplest way to add it to unit test
-                panel.PixelOffset = 1;
+            ////    //instead pixeloffset > 0 there could be pretty complex sequence for repro
+            ////    //it involves add/remove/scroll to end multiple actions
+            ////    //which i can't find so far :(, but this is the simplest way to add it to unit test
+            ////    panel.PixelOffset = 1;
 
-                //here scroll to end -> IndexOutOfRangeException is thrown
-                target.Scroll.Offset = new Vector(0, 2);
+            ////    //here scroll to end -> IndexOutOfRangeException is thrown
+            ////    target.Scroll.Offset = new Vector(0, 2);
 
-                Assert.True(true);
-            }
+            ////    Assert.True(true);
+            ////}
         }
 
         [Fact]
@@ -600,9 +602,7 @@ namespace Avalonia.Controls.UnitTests
                     Content = new ItemsPresenter
                     {
                         Name = "PART_ItemsPresenter",
-                        [~ItemsPresenter.ItemsProperty] = parent.GetObservable(ItemsControl.ItemsProperty).ToBinding(),
                         [~ItemsPresenter.ItemsPanelProperty] = parent.GetObservable(ItemsControl.ItemsPanelProperty).ToBinding(),
-                        [~ItemsPresenter.VirtualizationModeProperty] = parent.GetObservable(ListBox.VirtualizationModeProperty).ToBinding(),
                     }.RegisterInNameScope(scope)
                 }.RegisterInNameScope(scope));
         }

+ 0 - 1
tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs

@@ -93,7 +93,6 @@ namespace Avalonia.Controls.UnitTests
                 Content = new ItemsPresenter
                 {
                     Name = "PART_ItemsPresenter",
-                    [~ItemsPresenter.ItemsProperty] = ((Control)parent).GetObservable(ItemsControl.ItemsProperty).ToBinding(),
                 }.RegisterInNameScope(scope)
             };
         }

+ 0 - 1
tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs

@@ -324,7 +324,6 @@ namespace Avalonia.Controls.UnitTests
                 Content = new ItemsPresenter
                 {
                     Name = "PART_ItemsPresenter",
-                    [~ItemsPresenter.ItemsProperty] = parent.GetObservable(ItemsControl.ItemsProperty).ToBinding(),
                 }.RegisterInNameScope(scope)
             };
         }

+ 732 - 732
tests/Avalonia.Controls.UnitTests/Presenters/CarouselPresenterTests.cs

@@ -1,732 +1,732 @@
-using System.Linq;
-using Moq;
-using Avalonia.Controls.Generators;
-using Avalonia.Controls.Presenters;
-using Avalonia.Controls.Templates;
-using Xunit;
-using System.Collections.ObjectModel;
-using System.Collections;
-
-namespace Avalonia.Controls.UnitTests.Presenters
-{
-    public class CarouselPresenterTests
-    {
-        [Fact]
-        public void Should_Register_With_Host_When_TemplatedParent_Set()
-        {
-            var host = new Carousel();
-            var target = new CarouselPresenter();
-
-            Assert.Null(host.Presenter);
-
-            target.SetValue(Control.TemplatedParentProperty, host);
-
-            Assert.Same(target, host.Presenter);
-        }
-
-        [Fact]
-        public void ApplyTemplate_Should_Create_Panel()
-        {
-            var target = new CarouselPresenter
-            {
-                ItemsPanel = new FuncTemplate<Panel>(() => new Panel()),
-            };
-
-            target.ApplyTemplate();
-
-            Assert.IsType<Panel>(target.Panel);
-        }
-
-        [Fact]
-        public void ItemContainerGenerator_Should_Be_Picked_Up_From_TemplatedControl()
-        {
-            var parent = new TestItemsControl();
-            var target = new CarouselPresenter
-            {
-                [StyledElement.TemplatedParentProperty] = parent,
-            };
-
-            Assert.IsType<ItemContainerGenerator<TestItem>>(target.ItemContainerGenerator);
-        }
-
-        public class Virtualized
-        {
-            [Fact]
-            public void Should_Initially_Materialize_Selected_Container()
-            {
-                var target = new CarouselPresenter
-                {
-                    Items = new[] { "foo", "bar" },
-                    SelectedIndex = 0,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-
-                AssertSingle(target);
-            }
-
-            [Fact]
-            public void Should_Initially_Materialize_Nothing_If_No_Selected_Container()
-            {
-                var target = new CarouselPresenter
-                {
-                    Items = new[] { "foo", "bar" },
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-
-                Assert.Empty(target.Panel.Children);
-                Assert.Empty(target.ItemContainerGenerator.Containers);
-            }
-
-            [Fact]
-            public void Switching_To_Virtualized_Should_Reset_Containers()
-            {
-                var target = new CarouselPresenter
-                {
-                    Items = new[] { "foo", "bar" },
-                    SelectedIndex = 0,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-                target.IsVirtualized = true;
-
-                AssertSingle(target);
-            }
-
-            [Fact]
-            public void Changing_SelectedIndex_Should_Show_Page()
-            {
-                var target = new CarouselPresenter
-                {
-                    Items = new[] { "foo", "bar" },
-                    SelectedIndex = 0,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-                AssertSingle(target);
-
-                target.SelectedIndex = 1;
-                AssertSingle(target);
-            }
-
-            [Fact]
-            public void Should_Remove_NonCurrent_Page()
-            {
-                var target = new CarouselPresenter
-                {
-                    Items = new[] { "foo", "bar" },
-                    IsVirtualized = true,
-                    SelectedIndex = 0,
-                };
-
-                target.ApplyTemplate();
-                AssertSingle(target);
-
-                target.SelectedIndex = 1;
-                AssertSingle(target);
-
-            }
-
-            [Fact]
-            public void Should_Handle_Inserting_Item_At_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-
-                items.Insert(1, "item1a");
-                AssertSingle(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Inserting_Item_Before_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 2,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-
-                items.Insert(1, "item1a");
-                AssertSingle(target);
-            }
-
-            [Fact]
-            public void Should_Do_Nothing_When_Inserting_Item_After_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-                var child = AssertSingle(target);
-                items.Insert(2, "after");
-                Assert.Same(child, AssertSingle(target));
-            }
-
-            [Fact]
-            public void Should_Handle_Removing_Item_At_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-
-                items.RemoveAt(1);
-                AssertSingle(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Removing_Item_Before_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-
-                items.RemoveAt(0);
-                AssertSingle(target);
-            }
-
-            [Fact]
-            public void Should_Do_Nothing_When_Removing_Item_After_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-                var child = AssertSingle(target);
-                items.RemoveAt(2);
-                Assert.Same(child, AssertSingle(target));
-            }
-
-            [Fact]
-            public void Should_Handle_Removing_SelectedItem_When_Its_Last()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 2,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-
-                items.RemoveAt(2);
-                Assert.Equal(1, target.SelectedIndex);
-                AssertSingle(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Removing_Last_Item()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 0,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-
-                items.RemoveAt(0);
-                Assert.Empty(target.Panel.Children);
-                Assert.Empty(target.ItemContainerGenerator.Containers);
-            }
-
-            [Fact]
-            public void Should_Handle_Replacing_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-
-                items[1] = "replaced";
-                AssertSingle(target);
-            }
-
-            [Fact]
-            public void Should_Do_Nothing_When_Replacing_Non_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-                var child = AssertSingle(target);
-                items[0] = "replaced";
-                Assert.Same(child, AssertSingle(target));
-            }
-
-            [Fact]
-            public void Should_Handle_Moving_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-
-                items.Move(1, 0);
-                AssertSingle(target);
-            }
-
-            private static Control AssertSingle(CarouselPresenter target)
-            {
-                var items = (IList)target.Items;
-                var index = target.SelectedIndex;
-                var content = items[index];
-                var child = Assert.Single(target.Panel.Children);
-                var presenter = Assert.IsType<ContentPresenter>(child);
-                var container = Assert.Single(target.ItemContainerGenerator.Containers);
-                var visible = Assert.Single(target.Panel.Children.Where(x => x.IsVisible));
-
-                Assert.Same(child, container.ContainerControl);
-                Assert.Same(child, visible);
-                Assert.Equal(content, presenter.Content);
-                Assert.Equal(content, container.Item);
-                Assert.Equal(index, container.Index);
-
-                return child;
-            }
-        }
-
-        public class NonVirtualized
-        {
-            [Fact]
-            public void Should_Initially_Materialize_All_Containers()
-            {
-                var target = new CarouselPresenter
-                {
-                    Items = new[] { "foo", "bar" },
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Should_Initially_Show_Selected_Item()
-            {
-                var target = new CarouselPresenter
-                {
-                    Items = new[] { "foo", "bar" },
-                    SelectedIndex = 1,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Switching_To_Non_Virtualized_Should_Reset_Containers()
-            {
-                var target = new CarouselPresenter
-                {
-                    Items = new[] { "foo", "bar" },
-                    SelectedIndex = 0,
-                    IsVirtualized = true,
-                };
-
-                target.ApplyTemplate();
-                target.IsVirtualized = false;
-
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Changing_SelectedIndex_Should_Show_Page()
-            {
-                var target = new CarouselPresenter
-                {
-                    Items = new[] { "foo", "bar" },
-                    SelectedIndex = 0,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-                AssertAll(target);
-
-                target.SelectedIndex = 1;
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Inserting_Item_At_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-
-                items.Insert(1, "item1a");
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Inserting_Item_Before_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 2,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-
-                items.Insert(1, "item1a");
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Should_Do_Handle_Inserting_Item_After_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-                items.Insert(2, "after");
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Removing_Item_At_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-
-                items.RemoveAt(1);
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Removing_Item_Before_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-
-                items.RemoveAt(0);
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Removing_Item_After_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-                items.RemoveAt(2);
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Removing_SelectedItem_When_Its_Last()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 2,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-
-                items.RemoveAt(2);
-                Assert.Equal(1, target.SelectedIndex);
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Removing_Last_Item()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 0,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-
-                items.RemoveAt(0);
-                Assert.Empty(target.Panel.Children);
-                Assert.Empty(target.ItemContainerGenerator.Containers);
-            }
-
-            [Fact]
-            public void Should_Handle_Replacing_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-
-                items[1] = "replaced";
-                AssertAll(target);
-            }
-
-            [Fact]
-            public void Should_Handle_Moving_SelectedItem()
-            {
-                var items = new ObservableCollection<string>
-                {
-                    "item0",
-                    "item1",
-                    "item2",
-                };
-
-                var target = new CarouselPresenter
-                {
-                    Items = items,
-                    SelectedIndex = 1,
-                    IsVirtualized = false,
-                };
-
-                target.ApplyTemplate();
-
-                items.Move(1, 0);
-                AssertAll(target);
-            }
-
-            private static void AssertAll(CarouselPresenter target)
-            {
-                var items = (IList)target.Items;
-
-                Assert.Equal(items?.Count ?? 0, target.Panel.Children.Count);
-                Assert.Equal(items?.Count ?? 0, target.ItemContainerGenerator.Containers.Count());
-
-                for (var i = 0; i < items?.Count; ++i)
-                {
-                    var content = items[i];
-                    var child = target.Panel.Children[i];
-                    var presenter = Assert.IsType<ContentPresenter>(child);
-                    var container = target.ItemContainerGenerator.ContainerFromIndex(i);
-
-                    Assert.Same(child, container);
-                    Assert.Equal(i == target.SelectedIndex, child.IsVisible);
-                    Assert.Equal(content, presenter.Content);
-                    Assert.Equal(i, target.ItemContainerGenerator.IndexFromContainer(container));
-                }
-            }
-        }
-
-        private class TestItem : ContentControl
-        {
-        }
-
-        private class TestItemsControl : ItemsControl
-        {
-            protected override IItemContainerGenerator CreateItemContainerGenerator()
-            {
-                return new ItemContainerGenerator<TestItem>(this, TestItem.ContentProperty, null);
-            }
-        }
-    }
-}
+////using System.Linq;
+////using Moq;
+////using Avalonia.Controls.Generators;
+////using Avalonia.Controls.Presenters;
+////using Avalonia.Controls.Templates;
+////using Xunit;
+////using System.Collections.ObjectModel;
+////using System.Collections;
+
+////namespace Avalonia.Controls.UnitTests.Presenters
+////{
+////    public class CarouselPresenterTests
+////    {
+////        [Fact]
+////        public void Should_Register_With_Host_When_TemplatedParent_Set()
+////        {
+////            var host = new Carousel();
+////            var target = new CarouselPresenter();
+
+////            Assert.Null(host.Presenter);
+
+////            target.SetValue(Control.TemplatedParentProperty, host);
+
+////            Assert.Same(target, host.Presenter);
+////        }
+
+////        [Fact]
+////        public void ApplyTemplate_Should_Create_Panel()
+////        {
+////            var target = new CarouselPresenter
+////            {
+////                ItemsPanel = new FuncTemplate<Panel>(() => new Panel()),
+////            };
+
+////            target.ApplyTemplate();
+
+////            Assert.IsType<Panel>(target.Panel);
+////        }
+
+////        [Fact]
+////        public void ItemContainerGenerator_Should_Be_Picked_Up_From_TemplatedControl()
+////        {
+////            var parent = new TestItemsControl();
+////            var target = new CarouselPresenter
+////            {
+////                [StyledElement.TemplatedParentProperty] = parent,
+////            };
+
+////            Assert.IsType<ItemContainerGenerator<TestItem>>(target.ItemContainerGenerator);
+////        }
+
+////        public class Virtualized
+////        {
+////            [Fact]
+////            public void Should_Initially_Materialize_Selected_Container()
+////            {
+////                var target = new CarouselPresenter
+////                {
+////                    Items = new[] { "foo", "bar" },
+////                    SelectedIndex = 0,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+
+////                AssertSingle(target);
+////            }
+
+////            [Fact]
+////            public void Should_Initially_Materialize_Nothing_If_No_Selected_Container()
+////            {
+////                var target = new CarouselPresenter
+////                {
+////                    Items = new[] { "foo", "bar" },
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+
+////                Assert.Empty(target.Panel.Children);
+////                Assert.Empty(target.ItemContainerGenerator.Containers);
+////            }
+
+////            [Fact]
+////            public void Switching_To_Virtualized_Should_Reset_Containers()
+////            {
+////                var target = new CarouselPresenter
+////                {
+////                    Items = new[] { "foo", "bar" },
+////                    SelectedIndex = 0,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+////                target.IsVirtualized = true;
+
+////                AssertSingle(target);
+////            }
+
+////            [Fact]
+////            public void Changing_SelectedIndex_Should_Show_Page()
+////            {
+////                var target = new CarouselPresenter
+////                {
+////                    Items = new[] { "foo", "bar" },
+////                    SelectedIndex = 0,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+////                AssertSingle(target);
+
+////                target.SelectedIndex = 1;
+////                AssertSingle(target);
+////            }
+
+////            [Fact]
+////            public void Should_Remove_NonCurrent_Page()
+////            {
+////                var target = new CarouselPresenter
+////                {
+////                    Items = new[] { "foo", "bar" },
+////                    IsVirtualized = true,
+////                    SelectedIndex = 0,
+////                };
+
+////                target.ApplyTemplate();
+////                AssertSingle(target);
+
+////                target.SelectedIndex = 1;
+////                AssertSingle(target);
+
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Inserting_Item_At_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.Insert(1, "item1a");
+////                AssertSingle(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Inserting_Item_Before_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 2,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.Insert(1, "item1a");
+////                AssertSingle(target);
+////            }
+
+////            [Fact]
+////            public void Should_Do_Nothing_When_Inserting_Item_After_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+////                var child = AssertSingle(target);
+////                items.Insert(2, "after");
+////                Assert.Same(child, AssertSingle(target));
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Removing_Item_At_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.RemoveAt(1);
+////                AssertSingle(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Removing_Item_Before_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.RemoveAt(0);
+////                AssertSingle(target);
+////            }
+
+////            [Fact]
+////            public void Should_Do_Nothing_When_Removing_Item_After_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+////                var child = AssertSingle(target);
+////                items.RemoveAt(2);
+////                Assert.Same(child, AssertSingle(target));
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Removing_SelectedItem_When_Its_Last()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 2,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.RemoveAt(2);
+////                Assert.Equal(1, target.SelectedIndex);
+////                AssertSingle(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Removing_Last_Item()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 0,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.RemoveAt(0);
+////                Assert.Empty(target.Panel.Children);
+////                Assert.Empty(target.ItemContainerGenerator.Containers);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Replacing_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items[1] = "replaced";
+////                AssertSingle(target);
+////            }
+
+////            [Fact]
+////            public void Should_Do_Nothing_When_Replacing_Non_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+////                var child = AssertSingle(target);
+////                items[0] = "replaced";
+////                Assert.Same(child, AssertSingle(target));
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Moving_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.Move(1, 0);
+////                AssertSingle(target);
+////            }
+
+////            private static Control AssertSingle(CarouselPresenter target)
+////            {
+////                var items = (IList)target.Items;
+////                var index = target.SelectedIndex;
+////                var content = items[index];
+////                var child = Assert.Single(target.Panel.Children);
+////                var presenter = Assert.IsType<ContentPresenter>(child);
+////                var container = Assert.Single(target.ItemContainerGenerator.Containers);
+////                var visible = Assert.Single(target.Panel.Children.Where(x => x.IsVisible));
+
+////                Assert.Same(child, container.ContainerControl);
+////                Assert.Same(child, visible);
+////                Assert.Equal(content, presenter.Content);
+////                Assert.Equal(content, container.Item);
+////                Assert.Equal(index, container.Index);
+
+////                return child;
+////            }
+////        }
+
+////        public class NonVirtualized
+////        {
+////            [Fact]
+////            public void Should_Initially_Materialize_All_Containers()
+////            {
+////                var target = new CarouselPresenter
+////                {
+////                    Items = new[] { "foo", "bar" },
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Should_Initially_Show_Selected_Item()
+////            {
+////                var target = new CarouselPresenter
+////                {
+////                    Items = new[] { "foo", "bar" },
+////                    SelectedIndex = 1,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Switching_To_Non_Virtualized_Should_Reset_Containers()
+////            {
+////                var target = new CarouselPresenter
+////                {
+////                    Items = new[] { "foo", "bar" },
+////                    SelectedIndex = 0,
+////                    IsVirtualized = true,
+////                };
+
+////                target.ApplyTemplate();
+////                target.IsVirtualized = false;
+
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Changing_SelectedIndex_Should_Show_Page()
+////            {
+////                var target = new CarouselPresenter
+////                {
+////                    Items = new[] { "foo", "bar" },
+////                    SelectedIndex = 0,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+////                AssertAll(target);
+
+////                target.SelectedIndex = 1;
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Inserting_Item_At_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.Insert(1, "item1a");
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Inserting_Item_Before_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 2,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.Insert(1, "item1a");
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Should_Do_Handle_Inserting_Item_After_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+////                items.Insert(2, "after");
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Removing_Item_At_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.RemoveAt(1);
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Removing_Item_Before_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.RemoveAt(0);
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Removing_Item_After_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+////                items.RemoveAt(2);
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Removing_SelectedItem_When_Its_Last()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 2,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.RemoveAt(2);
+////                Assert.Equal(1, target.SelectedIndex);
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Removing_Last_Item()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 0,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.RemoveAt(0);
+////                Assert.Empty(target.Panel.Children);
+////                Assert.Empty(target.ItemContainerGenerator.Containers);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Replacing_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items[1] = "replaced";
+////                AssertAll(target);
+////            }
+
+////            [Fact]
+////            public void Should_Handle_Moving_SelectedItem()
+////            {
+////                var items = new ObservableCollection<string>
+////                {
+////                    "item0",
+////                    "item1",
+////                    "item2",
+////                };
+
+////                var target = new CarouselPresenter
+////                {
+////                    Items = items,
+////                    SelectedIndex = 1,
+////                    IsVirtualized = false,
+////                };
+
+////                target.ApplyTemplate();
+
+////                items.Move(1, 0);
+////                AssertAll(target);
+////            }
+
+////            private static void AssertAll(CarouselPresenter target)
+////            {
+////                var items = (IList)target.Items;
+
+////                Assert.Equal(items?.Count ?? 0, target.Panel.Children.Count);
+////                Assert.Equal(items?.Count ?? 0, target.ItemContainerGenerator.Containers.Count());
+
+////                for (var i = 0; i < items?.Count; ++i)
+////                {
+////                    var content = items[i];
+////                    var child = target.Panel.Children[i];
+////                    var presenter = Assert.IsType<ContentPresenter>(child);
+////                    var container = target.ItemContainerGenerator.ContainerFromIndex(i);
+
+////                    Assert.Same(child, container);
+////                    Assert.Equal(i == target.SelectedIndex, child.IsVisible);
+////                    Assert.Equal(content, presenter.Content);
+////                    Assert.Equal(i, target.ItemContainerGenerator.IndexFromContainer(container));
+////                }
+////            }
+////        }
+
+////        private class TestItem : ContentControl
+////        {
+////        }
+
+////        private class TestItemsControl : ItemsControl
+////        {
+////            protected override IItemContainerGenerator CreateItemContainerGenerator()
+////            {
+////                return new ItemContainerGenerator<TestItem>(this, TestItem.ContentProperty, null);
+////            }
+////        }
+////    }
+////}

+ 85 - 285
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs

@@ -1,14 +1,15 @@
+using System;
+using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Linq;
-using Moq;
-using Avalonia.Collections;
-using Avalonia.Controls.Generators;
 using Avalonia.Controls.Presenters;
 using Avalonia.Controls.Templates;
-using Avalonia.Input;
+using Avalonia.UnitTests;
 using Avalonia.VisualTree;
 using Xunit;
 
+#nullable enable
+
 namespace Avalonia.Controls.UnitTests.Presenters
 {
     public class ItemsPresenterTests
@@ -27,327 +28,126 @@ namespace Avalonia.Controls.UnitTests.Presenters
         }
 
         [Fact]
-        public void Should_Add_Containers()
-        {
-            var target = new ItemsPresenter
-            {
-                Items = new[] { "foo", "bar" },
-            };
-
-            target.ApplyTemplate();
-
-            Assert.Equal(2, target.Panel.Children.Count);
-            Assert.IsType<ContentPresenter>(target.Panel.Children[0]);
-            Assert.IsType<ContentPresenter>(target.Panel.Children[1]);
-            Assert.Equal("foo", ((ContentPresenter)target.Panel.Children[0]).Content);
-            Assert.Equal("bar", ((ContentPresenter)target.Panel.Children[1]).Content);
-        }
-
-        [Fact]
-        public void Should_Add_Containers_Of_Correct_Type()
-        {
-            var target = new ItemsPresenter
-            {
-                Items = new[] { "foo", "bar" },
-            };
-
-            target.ItemContainerGenerator = new ItemContainerGenerator<ListBoxItem>(
-                target, 
-                ListBoxItem.ContentProperty,
-                null);
-            target.ApplyTemplate();
-
-            Assert.Equal(2, target.Panel.Children.Count);
-            Assert.IsType<ListBoxItem>(target.Panel.Children[0]);
-            Assert.IsType<ListBoxItem>(target.Panel.Children[1]);
-        }
-
-        [Fact]
-        public void Should_Create_Containers_Only_Once()
-        {
-            var parent = new TestItemsControl();
-            var target = new ItemsPresenter
-            {
-                Items = new[] { "foo", "bar" },
-                [StyledElement.TemplatedParentProperty] = parent,
-            };
-            var raised = 0;
-
-            parent.ItemContainerGenerator.Materialized += (s, e) => ++raised;
-
-            target.ApplyTemplate();
-
-            Assert.Equal(2, target.Panel.Children.Count);
-            Assert.Equal(2, raised);
-        }
-
-        [Fact]
-        public void ItemContainerGenerator_Should_Be_Picked_Up_From_TemplatedControl()
-        {
-            var parent = new TestItemsControl();
-            var target = new ItemsPresenter
-            {
-                [StyledElement.TemplatedParentProperty] = parent,
-            };
-
-            Assert.IsType<ItemContainerGenerator<TestItem>>(target.ItemContainerGenerator);
-        }
-
-        [Fact]
-        public void Should_Remove_Containers()
+        public void Panel_Should_Be_Visual_Child()
         {
-            var items = new AvaloniaList<string>(new[] { "foo", "bar" });
-            var target = new ItemsPresenter
-            {
-                Items = items,
-            };
-
-            target.ApplyTemplate();
-            items.RemoveAt(0);
+            var (target, _, _) = CreateTarget();
+            var child = target.GetVisualChildren().Single();
 
-            Assert.Single(target.Panel.Children);
-            Assert.Equal("bar", ((ContentPresenter)target.Panel.Children[0]).Content);
-            Assert.Equal("bar", ((ContentPresenter)target.ItemContainerGenerator.ContainerFromIndex(0)).Content);
+            Assert.Equal(target.Panel, child);
         }
 
-        [Fact]
-        public void Clearing_Items_Should_Remove_Containers()
+        public class NonVirtualizingPanel
         {
-            var items = new ObservableCollection<string> { "foo", "bar" };
-            var target = new ItemsPresenter
+            [Fact]
+            public void Creates_Containers_For_Initial_Items()
             {
-                Items = items,
-            };
+                using var app = Start();
+                var items = new[] { "foo", "bar", "baz" };
+                var (target, _, _) = CreateTarget(items);
+                var panel = Assert.IsType<StackPanel>(target.Panel);
 
-            target.ApplyTemplate();
-            items.Clear();
-
-            Assert.Empty(target.Panel.Children);
-            Assert.Empty(target.ItemContainerGenerator.Containers);
-        }
+                AssertContainers(panel, items);
+            }
 
-        [Fact]
-        public void Replacing_Items_Should_Update_Containers()
-        {
-            var items = new ObservableCollection<string> { "foo", "bar", "baz" };
-            var target = new ItemsPresenter
+            [Fact]
+            public void Creates_Containers_For_Inserted_Items()
             {
-                Items = items,
-            };
+                using var app = Start();
+                var items = new ObservableCollection<string>(new[] { "foo", "bar", "baz" });
+                var (target, _, root) = CreateTarget(items);
+                var panel = Assert.IsType<StackPanel>(target.Panel);
 
-            target.ApplyTemplate();
-            items[1] = "baz";
+                items.Insert(1, "foo2");
+                root.LayoutManager.ExecuteLayoutPass();
 
-            var text = target.Panel.Children
-                .OfType<ContentPresenter>()
-                .Select(x => x.Content)
-                .ToList();
-
-            Assert.Equal(new[] { "foo", "baz", "baz" }, text);
-        }
+                AssertContainers(panel, items);
+            }
 
-        [Fact]
-        public void Moving_Items_Should_Update_Containers()
-        {
-            var items = new ObservableCollection<string> { "foo", "bar", "baz" };
-            var target = new ItemsPresenter
+            [Fact]
+            public void Removes_Containers_For_Removed_Items()
             {
-                Items = items,
-            };
+                using var app = Start();
+                var items = new ObservableCollection<string>(new[] { "foo", "bar", "baz" });
+                var (target, _, root) = CreateTarget(items);
+                var panel = Assert.IsType<StackPanel>(target.Panel);
 
-            target.ApplyTemplate();
-            items.Move(2, 1);
+                items.RemoveAt(1);
+                root.LayoutManager.ExecuteLayoutPass();
 
-            var text = target.Panel.Children
-                .OfType<ContentPresenter>()
-                .Select(x => x.Content)
-                .ToList();
-
-            Assert.Equal(new[] { "foo", "baz", "bar" }, text);
-        }
+                AssertContainers(panel, items);
+            }
 
-        [Fact]
-        public void Inserting_Items_Should_Update_Containers()
-        {
-            var items = new ObservableCollection<string> { "foo", "bar", "baz" };
-            var target = new ItemsPresenter
+            [Fact]
+            public void Updates_Containers_For_Moved_Items()
             {
-                Items = items,
-            };
-
-            target.ApplyTemplate();
-            items.Insert(2, "insert");
-
-            var text = target.Panel.Children
-                .OfType<ContentPresenter>()
-                .Select(x => x.Content)
-                .ToList();
-
-            Assert.Equal(new[] { "foo", "bar", "insert", "baz" }, text);
-        }
+                using var app = Start();
+                var items = new ObservableCollection<string>(new[] { "foo", "bar", "baz" });
+                var (target, _, root) = CreateTarget(items);
+                var panel = Assert.IsType<StackPanel>(target.Panel);
 
-        [Fact]
-        public void Setting_Items_To_Null_Should_Remove_Containers()
-        {
-            var target = new ItemsPresenter
-            {
-                Items = new[] { "foo", "bar" },
-            };
+                items.Move(0, 2);
+                root.LayoutManager.ExecuteLayoutPass();
 
-            target.ApplyTemplate();
-            target.Items = null;
-
-            Assert.Empty(target.Panel.Children);
-            Assert.Empty(target.ItemContainerGenerator.Containers);
-        }
-
-        [Fact]
-        public void Should_Handle_Null_Items()
-        {
-            var items = new AvaloniaList<string>(new[] { "foo", null, "bar" });
+                AssertContainers(panel, items);
+            }
 
-            var target = new ItemsPresenter
+            [Fact]
+            public void Updates_Containers_For_Replaced_Items()
             {
-                Items = items,
-            };
-
-            target.ApplyTemplate();
+                using var app = Start();
+                var items = new ObservableCollection<string>(new[] { "foo", "bar", "baz" });
+                var (target, _, root) = CreateTarget(items);
+                var panel = Assert.IsType<StackPanel>(target.Panel);
 
-            var text = target.Panel.Children.Cast<ContentPresenter>().Select(x => x.Content).ToList();
+                items[1] = "bar2";
+                root.LayoutManager.ExecuteLayoutPass();
 
-            Assert.Equal(new[] { "foo", null, "bar" }, text);
-            Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(0));
-            Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(1));
-            Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(2));
-
-            items.RemoveAt(1);
-
-            text = target.Panel.Children.Cast<ContentPresenter>().Select(x => x.Content).ToList();
-
-            Assert.Equal(new[] { "foo", "bar" }, text);
-            Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(0));
-            Assert.NotNull(target.ItemContainerGenerator.ContainerFromIndex(1));
-        }
+                AssertContainers(panel, items);
+            }
 
-        [Fact]
-        public void Inserting_Then_Removing_Should_Add_Remove_Containers()
-        {
-            var items = new AvaloniaList<string>(Enumerable.Range(0, 5).Select(x => $"Item {x}"));
-            var toAdd = Enumerable.Range(0, 3).Select(x => $"Added Item {x}").ToArray();
-            var target = new ItemsPresenter
+            [Fact]
+            public void Updates_Containers_On_Items_Changed()
             {
-                VirtualizationMode = ItemVirtualizationMode.None,
-                Items = items,
-                ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Height = 10 }),
-            };
+                using var app = Start();
+                var items = new ObservableCollection<string>(new[] { "foo", "bar", "baz" });
+                var (target, itemsControl, root) = CreateTarget(items);
+                var panel = Assert.IsType<StackPanel>(target.Panel);
 
-            target.ApplyTemplate();
+                var newItems = new[] { "qux", "quux", "corge" };
+                itemsControl.Items = newItems;
+                root.LayoutManager.ExecuteLayoutPass();
 
-            Assert.Equal(items.Count, target.Panel.Children.Count);
-
-            foreach (var item in toAdd)
-            {
-                items.Insert(1, item);
+                AssertContainers(panel, newItems);
             }
 
-            Assert.Equal(items.Count, target.Panel.Children.Count);
-
-            foreach (var item in toAdd)
+            private static void AssertContainers(StackPanel panel, IReadOnlyList<string> items)
             {
-                items.Remove(item);
-            }
+                Assert.Equal(items.Count, panel.Children.Count);
 
-            Assert.Equal(items.Count, target.Panel.Children.Count);
+                for (var i = 0; i < items.Count; i++)
+                {
+                    var container = Assert.IsType<ContentPresenter>(panel.Children[i]);
+                    Assert.Equal(items[i], container.DataContext);
+                    Assert.Equal(items[i], container.Content);
+                }
+            }
         }
 
-        [Fact]
-        public void Should_Handle_Duplicate_Items()
+        private static (ItemsPresenter, ItemsControl, TestRoot) CreateTarget(IReadOnlyList<string>? items = null)
         {
-            var items = new AvaloniaList<int>(new[] { 1, 2, 1 });
+            var result = new ItemsPresenter();
 
-            var target = new ItemsPresenter
+            var itemsControl = new ItemsControl
             {
                 Items = items,
+                Template = new FuncControlTemplate<ItemsControl>((_, _) => result)
             };
 
-            target.ApplyTemplate();
-            items.RemoveAt(2);
-
-            var numbers = target.Panel.Children
-                .OfType<ContentPresenter>()
-                .Select(x => x.Content)
-                .Cast<int>();
-            Assert.Equal(new[] { 1, 2 }, numbers);
-        }
-
-        [Fact]
-        public void Panel_Should_Be_Created_From_ItemsPanel_Template()
-        {
-            var panel = new Panel();
-            var target = new ItemsPresenter
-            {
-                ItemsPanel = new FuncTemplate<Panel>(() => panel),
-            };
-
-            target.ApplyTemplate();
-
-            Assert.Same(panel, target.Panel);
-            Assert.Same(target, target.Panel.Parent);
+            var root = new TestRoot(itemsControl);
+            root.LayoutManager.ExecuteInitialLayoutPass();
+            return (result, itemsControl, root);
         }
 
-        [Fact]
-        public void Panel_TabNavigation_Should_Be_Set_To_Once()
-        {
-            var target = new ItemsPresenter();
-
-            target.ApplyTemplate();
-
-            Assert.Equal(KeyboardNavigationMode.Once, KeyboardNavigation.GetTabNavigation((InputElement)target.Panel));
-        }
-
-        [Fact]
-        public void Panel_TabNavigation_Should_Be_Set_To_ItemsPresenter_Value()
-        {
-            var target = new ItemsPresenter();
-
-            KeyboardNavigation.SetTabNavigation(target, KeyboardNavigationMode.Cycle);
-            target.ApplyTemplate();
-
-            Assert.Equal(KeyboardNavigationMode.Cycle, KeyboardNavigation.GetTabNavigation((InputElement)target.Panel));
-        }
-
-        [Fact]
-        public void Panel_Should_Be_Visual_Child()
-        {
-            var target = new ItemsPresenter();
-
-            target.ApplyTemplate();
-
-            var child = target.GetVisualChildren().Single();
-
-            Assert.Equal(target.Panel, child);
-        }
-
-        private class Item
-        {
-            public Item(string value)
-            {
-                Value = value;
-            }
-
-            public string Value { get; }
-        }
-
-        private class TestItem : ContentControl
-        {
-        }
-
-        private class TestItemsControl : ItemsControl
-        {
-            protected override IItemContainerGenerator CreateItemContainerGenerator()
-            {
-                return new ItemContainerGenerator<TestItem>(this, TestItem.ContentProperty, null);
-            }
-        }
+        private static IDisposable Start() => UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
     }
 }

+ 374 - 374
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs

@@ -1,374 +1,374 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Avalonia.Controls.Generators;
-using Avalonia.Controls.Presenters;
-using Avalonia.Controls.Primitives;
-using Avalonia.Controls.Templates;
-using Avalonia.Layout;
-using Avalonia.Platform;
-using Avalonia.Rendering;
-using Avalonia.UnitTests;
-using Avalonia.VisualTree;
-using Xunit;
-
-namespace Avalonia.Controls.UnitTests.Presenters
-{
-    public class ItemsPresenterTests_Virtualization
-    {
-        [Fact]
-        public void Should_Not_Create_Items_Before_Added_To_Visual_Tree()
-        {
-            var items = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
-            var target = new TestItemsPresenter(true)
-            {
-                Items = items,
-                ItemsPanel = VirtualizingPanelTemplate(Orientation.Vertical),
-                ItemTemplate = ItemTemplate(),
-                VirtualizationMode = ItemVirtualizationMode.Simple,
-            };
-
-            var scroller = new ScrollContentPresenter
-            {
-                Content = target,
-            };
-
-            scroller.UpdateChild();
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Empty(target.Panel.Children);
-
-            var root = new TestRoot
-            {
-                Child = scroller,
-            };
-
-            target.InvalidateMeasure();
-            target.Panel.InvalidateMeasure();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(10, target.Panel.Children.Count);
-        }
-
-        [Fact]
-        public void Should_Return_IsLogicalScrollEnabled_False_When_Has_No_Virtualizing_Panel()
-        {
-            var target = CreateTarget();
-            target.ClearValue(ItemsPresenter.ItemsPanelProperty);
-
-            target.ApplyTemplate();
-
-            Assert.False(((ILogicalScrollable)target).IsLogicalScrollEnabled);
-        }
-
-        [Fact]
-        public void Should_Return_IsLogicalScrollEnabled_False_When_VirtualizationMode_None()
-        {
-            var target = CreateTarget(ItemVirtualizationMode.None);
-
-            target.ApplyTemplate();
-
-            Assert.False(((ILogicalScrollable)target).IsLogicalScrollEnabled);
-        }
-
-        [Fact]
-        public void Should_Return_IsLogicalScrollEnabled_False_When_Doesnt_Have_ScrollPresenter_Parent()
-        {
-            var target = new ItemsPresenter
-            {
-                ItemsPanel = VirtualizingPanelTemplate(),
-                ItemTemplate = ItemTemplate(),
-                VirtualizationMode = ItemVirtualizationMode.Simple,
-            };
-
-            target.ApplyTemplate();
-
-            Assert.False(((ILogicalScrollable)target).IsLogicalScrollEnabled);
-        }
-
-        [Fact]
-        public void Should_Return_IsLogicalScrollEnabled_True()
-        {
-            var target = CreateTarget();
-
-            target.ApplyTemplate();
-
-            Assert.True(((ILogicalScrollable)target).IsLogicalScrollEnabled);
-        }
-
-        [Fact]
-        public void Parent_ScrollContentPresenter_Properties_Should_Be_Set()
-        {
-            var target = CreateTarget();
-
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            var scroll = (ScrollContentPresenter)target.Parent;
-            Assert.Equal(new Size(10, 20), scroll.Extent);
-            Assert.Equal(new Size(100, 10), scroll.Viewport);
-        }
-
-        [Fact]
-        public void Should_Fill_Panel_With_Containers()
-        {
-            var target = CreateTarget();
-
-            target.ApplyTemplate();
-
-            target.Measure(new Size(100, 100));
-            Assert.Equal(10, target.Panel.Children.Count);
-
-            target.Arrange(new Rect(0, 0, 100, 100));
-            Assert.Equal(10, target.Panel.Children.Count);
-        }
-
-        [Fact]
-        public void Should_Only_Create_Enough_Containers_To_Display_All_Items()
-        {
-            var target = CreateTarget(itemCount: 2);
-
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(2, target.Panel.Children.Count);
-        }
-
-        [Fact]
-        public void Should_Expand_To_Fit_Containers_When_Flexible_Size()
-        {
-            var target = CreateTarget();
-
-            target.ApplyTemplate();
-            target.Measure(Size.Infinity);
-            target.Arrange(new Rect(target.DesiredSize));
-
-            Assert.Equal(new Size(10, 200), target.DesiredSize);
-            Assert.Equal(new Size(10, 200), target.Bounds.Size);
-            Assert.Equal(20, target.Panel.Children.Count);
-        }
-
-        [Fact]
-        public void Initial_Item_DataContexts_Should_Be_Correct()
-        {
-            var target = CreateTarget();
-            var items = (IList<string>)target.Items;
-
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            for (var i = 0; i < target.Panel.Children.Count; ++i)
-            {
-                Assert.Equal(items[i], target.Panel.Children[i].DataContext);
-            }
-        }
-
-        [Fact]
-        public void Should_Add_New_Items_When_Control_Is_Enlarged()
-        {
-            var target = CreateTarget();
-            var items = (IList<string>)target.Items;
-
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(10, target.Panel.Children.Count);
-
-            target.Measure(new Size(120, 120));
-            target.Arrange(new Rect(0, 0, 100, 120));
-
-            Assert.Equal(12, target.Panel.Children.Count);
-
-            for (var i = 0; i < target.Panel.Children.Count; ++i)
-            {
-                Assert.Equal(items[i], target.Panel.Children[i].DataContext);
-            }
-        }
-
-        [Fact]
-        public void Should_Not_Create_Virtualizer_Before_Panel()
-        {
-            var target = CreateTarget();
-
-            Assert.Null(target.Panel);
-            Assert.Null(target.Virtualizer);
-        }
-
-        [Fact]
-        public void Changing_VirtualizationMode_None_To_Simple_Should_Update_Control()
-        {
-            var target = CreateTarget(mode: ItemVirtualizationMode.None);
-            var scroll = (ScrollContentPresenter)target.Parent;
-
-            scroll.Measure(new Size(100, 100));
-            scroll.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(20, target.Panel.Children.Count);
-            Assert.Equal(new Size(100, 200), scroll.Extent);
-            Assert.Equal(new Size(100, 100), scroll.Viewport);
-
-            target.VirtualizationMode = ItemVirtualizationMode.Simple;
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(10, target.Panel.Children.Count);
-            Assert.Equal(new Size(10, 20), scroll.Extent);
-            Assert.Equal(new Size(100, 10), scroll.Viewport);
-        }
-
-        [Fact]
-        public void Changing_VirtualizationMode_None_To_Simple_Should_Add_Correct_Number_Of_Controls()
-        {
-            using (UnitTestApplication.Start(new TestServices()))
-            {
-                var target = CreateTarget(mode: ItemVirtualizationMode.None);
-                var scroll = (TestScroller)target.Parent;
-
-                scroll.Width = scroll.Height = 100;
-                scroll.LayoutManager.ExecuteInitialLayoutPass();
-
-                // Ensure than an intermediate measure pass doesn't add more controls than it
-                // should. This can happen if target gets measured with Size.Infinity which
-                // is what the available size should be when VirtualizationMode == None but not
-                // what it should after VirtualizationMode is changed to Simple.
-                target.Panel.Children.CollectionChanged += (s, e) =>
-                {
-                    Assert.InRange(target.Panel.Children.Count, 0, 10);
-                };
-
-                target.VirtualizationMode = ItemVirtualizationMode.Simple;
-                ((ILayoutRoot)scroll.GetVisualRoot()).LayoutManager.ExecuteLayoutPass();
-
-                Assert.Equal(10, target.Panel.Children.Count);
-            }
-        }
-
-        [Fact]
-        public void Changing_VirtualizationMode_Simple_To_None_Should_Update_Control()
-        {
-            var target = CreateTarget();
-            var scroll = (ScrollContentPresenter)target.Parent;
-
-            scroll.Measure(new Size(100, 100));
-            scroll.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(10, target.Panel.Children.Count);
-            Assert.Equal(new Size(10, 20), scroll.Extent);
-            Assert.Equal(new Size(100, 10), scroll.Viewport);
-
-            target.VirtualizationMode = ItemVirtualizationMode.None;
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            // Here - unlike changing the other way - we need to do a layout pass on the scroll
-            // content presenter as non-logical scroll values are only updated on arrange.
-            scroll.Measure(new Size(100, 100));
-            scroll.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(20, target.Panel.Children.Count);
-            Assert.Equal(new Size(100, 200), scroll.Extent);
-            Assert.Equal(new Size(100, 100), scroll.Viewport);
-        }
-
-        private static ItemsPresenter CreateTarget(
-            ItemVirtualizationMode mode = ItemVirtualizationMode.Simple,
-            Orientation orientation = Orientation.Vertical,
-            bool useContainers = true,
-            int itemCount = 20)
-        {
-            ItemsPresenter result;
-            var items = Enumerable.Range(0, itemCount).Select(x => $"Item {x}").ToList();
-
-            var scroller = new TestScroller
-            {
-                CanHorizontallyScroll = false,
-                CanVerticallyScroll = true,
-                Content = result = new TestItemsPresenter(useContainers)
-                {
-                    Items = items,
-                    ItemsPanel = VirtualizingPanelTemplate(orientation),
-                    ItemTemplate = ItemTemplate(),
-                    VirtualizationMode = mode,
-                }
-            };
-
-            scroller.UpdateChild();
-
-            return result;
-        }
-
-        private static IDataTemplate ItemTemplate()
-        {
-            return new FuncDataTemplate<string>((x, _) => new Canvas
-            {
-                Width = 10,
-                Height = 10,
-            });
-        }
-
-        private static ITemplate<Panel> VirtualizingPanelTemplate(
-            Orientation orientation = Orientation.Vertical)
-        {
-            return new FuncTemplate<Panel>(() => new VirtualizingStackPanel
-            {
-                Orientation = orientation,
-            });
-        }
-
-        private class TestScroller : ScrollContentPresenter, IRenderRoot, ILayoutRoot
-        {
-            public TestScroller()
-            {
-                LayoutManager = new LayoutManager(this);
-            }
-
-            public IRenderer Renderer { get; }
-            public Size ClientSize { get; }
-            public double RenderScaling => 1;
-
-            public Size MaxClientSize => Size.Infinity;
-
-            public double LayoutScaling => 1;
-
-            public ILayoutManager LayoutManager { get; }
-
-            public IRenderTarget CreateRenderTarget() => throw new NotImplementedException();
-            public void Invalidate(Rect rect) => throw new NotImplementedException();
-            public Point PointToClient(PixelPoint p) => throw new NotImplementedException();
-            public PixelPoint PointToScreen(Point p) => throw new NotImplementedException();
-        }
-
-        private class TestItemsPresenter : ItemsPresenter
-        {
-            private bool _useContainers;
-
-            public TestItemsPresenter(bool useContainers)
-            {
-                _useContainers = useContainers;
-            }
-
-            protected override IItemContainerGenerator CreateItemContainerGenerator()
-            {
-                return _useContainers ?
-                    new ItemContainerGenerator<TestContainer>(this, TestContainer.ContentProperty, null) :
-                    new ItemContainerGenerator(this);
-            }
-        }
-
-        private class TestContainer : ContentControl
-        {
-            public TestContainer()
-            {
-                Width = 10;
-                Height = 10;
-            }
-        }
-    }
-}
+////using System;
+////using System.Collections.Generic;
+////using System.Linq;
+////using Avalonia.Controls.Generators;
+////using Avalonia.Controls.Presenters;
+////using Avalonia.Controls.Primitives;
+////using Avalonia.Controls.Templates;
+////using Avalonia.Layout;
+////using Avalonia.Platform;
+////using Avalonia.Rendering;
+////using Avalonia.UnitTests;
+////using Avalonia.VisualTree;
+////using Xunit;
+
+////namespace Avalonia.Controls.UnitTests.Presenters
+////{
+////    public class ItemsPresenterTests_Virtualization
+////    {
+////        [Fact]
+////        public void Should_Not_Create_Items_Before_Added_To_Visual_Tree()
+////        {
+////            var items = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
+////            var target = new TestItemsPresenter(true)
+////            {
+////                Items = items,
+////                ItemsPanel = VirtualizingPanelTemplate(Orientation.Vertical),
+////                ItemTemplate = ItemTemplate(),
+////                VirtualizationMode = ItemVirtualizationMode.Simple,
+////            };
+
+////            var scroller = new ScrollContentPresenter
+////            {
+////                Content = target,
+////            };
+
+////            scroller.UpdateChild();
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Empty(target.Panel.Children);
+
+////            var root = new TestRoot
+////            {
+////                Child = scroller,
+////            };
+
+////            target.InvalidateMeasure();
+////            target.Panel.InvalidateMeasure();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(10, target.Panel.Children.Count);
+////        }
+
+////        [Fact]
+////        public void Should_Return_IsLogicalScrollEnabled_False_When_Has_No_Virtualizing_Panel()
+////        {
+////            var target = CreateTarget();
+////            target.ClearValue(ItemsPresenter.ItemsPanelProperty);
+
+////            target.ApplyTemplate();
+
+////            Assert.False(((ILogicalScrollable)target).IsLogicalScrollEnabled);
+////        }
+
+////        [Fact]
+////        public void Should_Return_IsLogicalScrollEnabled_False_When_VirtualizationMode_None()
+////        {
+////            var target = CreateTarget(ItemVirtualizationMode.None);
+
+////            target.ApplyTemplate();
+
+////            Assert.False(((ILogicalScrollable)target).IsLogicalScrollEnabled);
+////        }
+
+////        [Fact]
+////        public void Should_Return_IsLogicalScrollEnabled_False_When_Doesnt_Have_ScrollPresenter_Parent()
+////        {
+////            var target = new ItemsPresenter
+////            {
+////                ItemsPanel = VirtualizingPanelTemplate(),
+////                ItemTemplate = ItemTemplate(),
+////                VirtualizationMode = ItemVirtualizationMode.Simple,
+////            };
+
+////            target.ApplyTemplate();
+
+////            Assert.False(((ILogicalScrollable)target).IsLogicalScrollEnabled);
+////        }
+
+////        [Fact]
+////        public void Should_Return_IsLogicalScrollEnabled_True()
+////        {
+////            var target = CreateTarget();
+
+////            target.ApplyTemplate();
+
+////            Assert.True(((ILogicalScrollable)target).IsLogicalScrollEnabled);
+////        }
+
+////        [Fact]
+////        public void Parent_ScrollContentPresenter_Properties_Should_Be_Set()
+////        {
+////            var target = CreateTarget();
+
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            var scroll = (ScrollContentPresenter)target.Parent;
+////            Assert.Equal(new Size(10, 20), scroll.Extent);
+////            Assert.Equal(new Size(100, 10), scroll.Viewport);
+////        }
+
+////        [Fact]
+////        public void Should_Fill_Panel_With_Containers()
+////        {
+////            var target = CreateTarget();
+
+////            target.ApplyTemplate();
+
+////            target.Measure(new Size(100, 100));
+////            Assert.Equal(10, target.Panel.Children.Count);
+
+////            target.Arrange(new Rect(0, 0, 100, 100));
+////            Assert.Equal(10, target.Panel.Children.Count);
+////        }
+
+////        [Fact]
+////        public void Should_Only_Create_Enough_Containers_To_Display_All_Items()
+////        {
+////            var target = CreateTarget(itemCount: 2);
+
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(2, target.Panel.Children.Count);
+////        }
+
+////        [Fact]
+////        public void Should_Expand_To_Fit_Containers_When_Flexible_Size()
+////        {
+////            var target = CreateTarget();
+
+////            target.ApplyTemplate();
+////            target.Measure(Size.Infinity);
+////            target.Arrange(new Rect(target.DesiredSize));
+
+////            Assert.Equal(new Size(10, 200), target.DesiredSize);
+////            Assert.Equal(new Size(10, 200), target.Bounds.Size);
+////            Assert.Equal(20, target.Panel.Children.Count);
+////        }
+
+////        [Fact]
+////        public void Initial_Item_DataContexts_Should_Be_Correct()
+////        {
+////            var target = CreateTarget();
+////            var items = (IList<string>)target.Items;
+
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            for (var i = 0; i < target.Panel.Children.Count; ++i)
+////            {
+////                Assert.Equal(items[i], target.Panel.Children[i].DataContext);
+////            }
+////        }
+
+////        [Fact]
+////        public void Should_Add_New_Items_When_Control_Is_Enlarged()
+////        {
+////            var target = CreateTarget();
+////            var items = (IList<string>)target.Items;
+
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(10, target.Panel.Children.Count);
+
+////            target.Measure(new Size(120, 120));
+////            target.Arrange(new Rect(0, 0, 100, 120));
+
+////            Assert.Equal(12, target.Panel.Children.Count);
+
+////            for (var i = 0; i < target.Panel.Children.Count; ++i)
+////            {
+////                Assert.Equal(items[i], target.Panel.Children[i].DataContext);
+////            }
+////        }
+
+////        [Fact]
+////        public void Should_Not_Create_Virtualizer_Before_Panel()
+////        {
+////            var target = CreateTarget();
+
+////            Assert.Null(target.Panel);
+////            Assert.Null(target.Virtualizer);
+////        }
+
+////        [Fact]
+////        public void Changing_VirtualizationMode_None_To_Simple_Should_Update_Control()
+////        {
+////            var target = CreateTarget(mode: ItemVirtualizationMode.None);
+////            var scroll = (ScrollContentPresenter)target.Parent;
+
+////            scroll.Measure(new Size(100, 100));
+////            scroll.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(20, target.Panel.Children.Count);
+////            Assert.Equal(new Size(100, 200), scroll.Extent);
+////            Assert.Equal(new Size(100, 100), scroll.Viewport);
+
+////            target.VirtualizationMode = ItemVirtualizationMode.Simple;
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(10, target.Panel.Children.Count);
+////            Assert.Equal(new Size(10, 20), scroll.Extent);
+////            Assert.Equal(new Size(100, 10), scroll.Viewport);
+////        }
+
+////        [Fact]
+////        public void Changing_VirtualizationMode_None_To_Simple_Should_Add_Correct_Number_Of_Controls()
+////        {
+////            using (UnitTestApplication.Start(new TestServices()))
+////            {
+////                var target = CreateTarget(mode: ItemVirtualizationMode.None);
+////                var scroll = (TestScroller)target.Parent;
+
+////                scroll.Width = scroll.Height = 100;
+////                scroll.LayoutManager.ExecuteInitialLayoutPass();
+
+////                // Ensure than an intermediate measure pass doesn't add more controls than it
+////                // should. This can happen if target gets measured with Size.Infinity which
+////                // is what the available size should be when VirtualizationMode == None but not
+////                // what it should after VirtualizationMode is changed to Simple.
+////                target.Panel.Children.CollectionChanged += (s, e) =>
+////                {
+////                    Assert.InRange(target.Panel.Children.Count, 0, 10);
+////                };
+
+////                target.VirtualizationMode = ItemVirtualizationMode.Simple;
+////                ((ILayoutRoot)scroll.GetVisualRoot()).LayoutManager.ExecuteLayoutPass();
+
+////                Assert.Equal(10, target.Panel.Children.Count);
+////            }
+////        }
+
+////        [Fact]
+////        public void Changing_VirtualizationMode_Simple_To_None_Should_Update_Control()
+////        {
+////            var target = CreateTarget();
+////            var scroll = (ScrollContentPresenter)target.Parent;
+
+////            scroll.Measure(new Size(100, 100));
+////            scroll.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(10, target.Panel.Children.Count);
+////            Assert.Equal(new Size(10, 20), scroll.Extent);
+////            Assert.Equal(new Size(100, 10), scroll.Viewport);
+
+////            target.VirtualizationMode = ItemVirtualizationMode.None;
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            // Here - unlike changing the other way - we need to do a layout pass on the scroll
+////            // content presenter as non-logical scroll values are only updated on arrange.
+////            scroll.Measure(new Size(100, 100));
+////            scroll.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(20, target.Panel.Children.Count);
+////            Assert.Equal(new Size(100, 200), scroll.Extent);
+////            Assert.Equal(new Size(100, 100), scroll.Viewport);
+////        }
+
+////        private static ItemsPresenter CreateTarget(
+////            ItemVirtualizationMode mode = ItemVirtualizationMode.Simple,
+////            Orientation orientation = Orientation.Vertical,
+////            bool useContainers = true,
+////            int itemCount = 20)
+////        {
+////            ItemsPresenter result;
+////            var items = Enumerable.Range(0, itemCount).Select(x => $"Item {x}").ToList();
+
+////            var scroller = new TestScroller
+////            {
+////                CanHorizontallyScroll = false,
+////                CanVerticallyScroll = true,
+////                Content = result = new TestItemsPresenter(useContainers)
+////                {
+////                    Items = items,
+////                    ItemsPanel = VirtualizingPanelTemplate(orientation),
+////                    ItemTemplate = ItemTemplate(),
+////                    VirtualizationMode = mode,
+////                }
+////            };
+
+////            scroller.UpdateChild();
+
+////            return result;
+////        }
+
+////        private static IDataTemplate ItemTemplate()
+////        {
+////            return new FuncDataTemplate<string>((x, _) => new Canvas
+////            {
+////                Width = 10,
+////                Height = 10,
+////            });
+////        }
+
+////        private static ITemplate<Panel> VirtualizingPanelTemplate(
+////            Orientation orientation = Orientation.Vertical)
+////        {
+////            return new FuncTemplate<Panel>(() => new VirtualizingStackPanel
+////            {
+////                Orientation = orientation,
+////            });
+////        }
+
+////        private class TestScroller : ScrollContentPresenter, IRenderRoot, ILayoutRoot
+////        {
+////            public TestScroller()
+////            {
+////                LayoutManager = new LayoutManager(this);
+////            }
+
+////            public IRenderer Renderer { get; }
+////            public Size ClientSize { get; }
+////            public double RenderScaling => 1;
+
+////            public Size MaxClientSize => Size.Infinity;
+
+////            public double LayoutScaling => 1;
+
+////            public ILayoutManager LayoutManager { get; }
+
+////            public IRenderTarget CreateRenderTarget() => throw new NotImplementedException();
+////            public void Invalidate(Rect rect) => throw new NotImplementedException();
+////            public Point PointToClient(PixelPoint p) => throw new NotImplementedException();
+////            public PixelPoint PointToScreen(Point p) => throw new NotImplementedException();
+////        }
+
+////        private class TestItemsPresenter : ItemsPresenter
+////        {
+////            private bool _useContainers;
+
+////            public TestItemsPresenter(bool useContainers)
+////            {
+////                _useContainers = useContainers;
+////            }
+
+////            protected override IItemContainerGenerator CreateItemContainerGenerator()
+////            {
+////                return _useContainers ?
+////                    new ItemContainerGenerator<TestContainer>(this, TestContainer.ContentProperty, null) :
+////                    new ItemContainerGenerator(this);
+////            }
+////        }
+
+////        private class TestContainer : ContentControl
+////        {
+////            public TestContainer()
+////            {
+////                Width = 10;
+////                Height = 10;
+////            }
+////        }
+////    }
+////}

+ 911 - 911
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs

@@ -1,1110 +1,1110 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using Avalonia.Collections;
-using Avalonia.Controls.Generators;
-using Avalonia.Controls.Presenters;
-using Avalonia.Controls.Primitives;
-using Avalonia.Controls.Templates;
-using Avalonia.Input;
-using Avalonia.Layout;
-using Avalonia.LogicalTree;
-using Avalonia.Platform;
-using Avalonia.Rendering;
-using Avalonia.Styling;
-using Avalonia.UnitTests;
-using Xunit;
-
-namespace Avalonia.Controls.UnitTests.Presenters
-{
-    public class ItemsPresenterTests_Virtualization_Simple
-    {
-        [Fact]
-        public void Should_Return_Items_Count_For_Extent_Vertical()
-        {
-            var target = CreateTarget();
-
-            target.ApplyTemplate();
-
-            Assert.Equal(new Size(0, 20), ((ILogicalScrollable)target).Extent);
-        }
-
-        [Fact]
-        public void Should_Return_Items_Count_For_Extent_Horizontal()
-        {
-            var target = CreateTarget(orientation: Orientation.Horizontal);
-
-            target.ApplyTemplate();
-
-            Assert.Equal(new Size(20, 0), ((ILogicalScrollable)target).Extent);
-        }
-
-        [Fact]
-        public void Should_Have_Number_Of_Visible_Items_As_Viewport_Vertical()
-        {
-            var target = CreateTarget();
-
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(new Size(100, 10), ((ILogicalScrollable)target).Viewport);
-        }
-
-        [Fact]
-        public void Should_Have_Number_Of_Visible_Items_As_Viewport_Horizontal()
-        {
-            var target = CreateTarget(orientation: Orientation.Horizontal);
-
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(new Size(10, 100), ((ILogicalScrollable)target).Viewport);
-        }
-
-        [Fact]
-        public void Should_Add_Containers_When_Panel_Is_Not_Full()
-        {
-            var target = CreateTarget(itemCount: 5);
-            var items = (IList<string>)target.Items;
-
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(5, target.Panel.Children.Count);
-
-            items.Add("New Item");
-
-            Assert.Equal(6, target.Panel.Children.Count);
-        }
-
-        [Fact]
-        public void Should_Remove_Items_When_Control_Is_Shrank()
-        {
-            var target = CreateTarget();
-            var items = (IList<string>)target.Items;
-
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
-
-            Assert.Equal(10, target.Panel.Children.Count);
-
-            target.Measure(new Size(100, 80));
-            target.Arrange(new Rect(0, 0, 100, 80));
-
-            Assert.Equal(8, target.Panel.Children.Count);
-        }
-
-        [Fact]
-        public void Should_Add_New_Containers_At_Top_When_Control_Is_Scrolled_To_Bottom_And_Enlarged()
-        {
-            var target = CreateTarget();
-            var items = (IList<string>)target.Items;
+////using System;
+////using System.Collections;
+////using System.Collections.Generic;
+////using System.Collections.ObjectModel;
+////using System.Linq;
+////using Avalonia.Collections;
+////using Avalonia.Controls.Generators;
+////using Avalonia.Controls.Presenters;
+////using Avalonia.Controls.Primitives;
+////using Avalonia.Controls.Templates;
+////using Avalonia.Input;
+////using Avalonia.Layout;
+////using Avalonia.LogicalTree;
+////using Avalonia.Platform;
+////using Avalonia.Rendering;
+////using Avalonia.Styling;
+////using Avalonia.UnitTests;
+////using Xunit;
+
+////namespace Avalonia.Controls.UnitTests.Presenters
+////{
+////    public class ItemsPresenterTests_Virtualization_Simple
+////    {
+////        [Fact]
+////        public void Should_Return_Items_Count_For_Extent_Vertical()
+////        {
+////            var target = CreateTarget();
+
+////            target.ApplyTemplate();
+
+////            Assert.Equal(new Size(0, 20), ((ILogicalScrollable)target).Extent);
+////        }
+
+////        [Fact]
+////        public void Should_Return_Items_Count_For_Extent_Horizontal()
+////        {
+////            var target = CreateTarget(orientation: Orientation.Horizontal);
+
+////            target.ApplyTemplate();
+
+////            Assert.Equal(new Size(20, 0), ((ILogicalScrollable)target).Extent);
+////        }
+
+////        [Fact]
+////        public void Should_Have_Number_Of_Visible_Items_As_Viewport_Vertical()
+////        {
+////            var target = CreateTarget();
+
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(new Size(100, 10), ((ILogicalScrollable)target).Viewport);
+////        }
+
+////        [Fact]
+////        public void Should_Have_Number_Of_Visible_Items_As_Viewport_Horizontal()
+////        {
+////            var target = CreateTarget(orientation: Orientation.Horizontal);
+
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(new Size(10, 100), ((ILogicalScrollable)target).Viewport);
+////        }
+
+////        [Fact]
+////        public void Should_Add_Containers_When_Panel_Is_Not_Full()
+////        {
+////            var target = CreateTarget(itemCount: 5);
+////            var items = (IList<string>)target.Items;
+
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(5, target.Panel.Children.Count);
+
+////            items.Add("New Item");
+
+////            Assert.Equal(6, target.Panel.Children.Count);
+////        }
+
+////        [Fact]
+////        public void Should_Remove_Items_When_Control_Is_Shrank()
+////        {
+////            var target = CreateTarget();
+////            var items = (IList<string>)target.Items;
+
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
+
+////            Assert.Equal(10, target.Panel.Children.Count);
+
+////            target.Measure(new Size(100, 80));
+////            target.Arrange(new Rect(0, 0, 100, 80));
+
+////            Assert.Equal(8, target.Panel.Children.Count);
+////        }
+
+////        [Fact]
+////        public void Should_Add_New_Containers_At_Top_When_Control_Is_Scrolled_To_Bottom_And_Enlarged()
+////        {
+////            var target = CreateTarget();
+////            var items = (IList<string>)target.Items;
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            Assert.Equal(10, target.Panel.Children.Count);
+////            Assert.Equal(10, target.Panel.Children.Count);
 
-            ((IScrollable)target).Offset = new Vector(0, 10);
-            target.Measure(new Size(120, 120));
-            target.Arrange(new Rect(0, 0, 100, 120));
+////            ((IScrollable)target).Offset = new Vector(0, 10);
+////            target.Measure(new Size(120, 120));
+////            target.Arrange(new Rect(0, 0, 100, 120));
 
-            Assert.Equal(12, target.Panel.Children.Count);
+////            Assert.Equal(12, target.Panel.Children.Count);
 
-            for (var i = 0; i < target.Panel.Children.Count; ++i)
-            {
-                Assert.Equal(items[i + 8], target.Panel.Children[i].DataContext);
-            }
-        }
+////            for (var i = 0; i < target.Panel.Children.Count; ++i)
+////            {
+////                Assert.Equal(items[i + 8], target.Panel.Children[i].DataContext);
+////            }
+////        }
 
-        [Fact]
-        public void Should_Update_Containers_When_Items_Changes()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Should_Update_Containers_When_Items_Changes()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            target.Items = new[] { "foo", "bar", "baz" };
+////            target.Items = new[] { "foo", "bar", "baz" };
 
-            Assert.Equal(3, target.Panel.Children.Count);
-        }
+////            Assert.Equal(3, target.Panel.Children.Count);
+////        }
 
-        [Fact]
-        public void Should_Decrease_The_Viewport_Size_By_One_If_There_Is_A_Partial_Item()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Should_Decrease_The_Viewport_Size_By_One_If_There_Is_A_Partial_Item()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 95));
-            target.Arrange(new Rect(0, 0, 100, 95));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 95));
+////            target.Arrange(new Rect(0, 0, 100, 95));
 
-            Assert.Equal(new Size(100, 9), ((ILogicalScrollable)target).Viewport);
-        }
+////            Assert.Equal(new Size(100, 9), ((ILogicalScrollable)target).Viewport);
+////        }
 
-        [Fact]
-        public void Moving_To_And_From_The_End_With_Partial_Item_Should_Set_Panel_PixelOffset()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Moving_To_And_From_The_End_With_Partial_Item_Should_Set_Panel_PixelOffset()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 95));
-            target.Arrange(new Rect(0, 0, 100, 95));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 95));
+////            target.Arrange(new Rect(0, 0, 100, 95));
 
-            ((ILogicalScrollable)target).Offset = new Vector(0, 11);
+////            ((ILogicalScrollable)target).Offset = new Vector(0, 11);
 
-            var minIndex = target.ItemContainerGenerator.Containers.Min(x => x.Index);
-            Assert.Equal(new Vector(0, 11), ((ILogicalScrollable)target).Offset);
-            Assert.Equal(10, minIndex);
-            Assert.Equal(10, ((IVirtualizingPanel)target.Panel).PixelOffset);
+////            var minIndex = target.ItemContainerGenerator.Containers.Min(x => x.Index);
+////            Assert.Equal(new Vector(0, 11), ((ILogicalScrollable)target).Offset);
+////            Assert.Equal(10, minIndex);
+////            Assert.Equal(10, ((IVirtualizingPanel)target.Panel).PixelOffset);
 
-            ((ILogicalScrollable)target).Offset = new Vector(0, 10);
+////            ((ILogicalScrollable)target).Offset = new Vector(0, 10);
 
-            minIndex = target.ItemContainerGenerator.Containers.Min(x => x.Index);
-            Assert.Equal(new Vector(0, 10), ((ILogicalScrollable)target).Offset);
-            Assert.Equal(10, minIndex);
-            Assert.Equal(0, ((IVirtualizingPanel)target.Panel).PixelOffset);
+////            minIndex = target.ItemContainerGenerator.Containers.Min(x => x.Index);
+////            Assert.Equal(new Vector(0, 10), ((ILogicalScrollable)target).Offset);
+////            Assert.Equal(10, minIndex);
+////            Assert.Equal(0, ((IVirtualizingPanel)target.Panel).PixelOffset);
 
-            ((ILogicalScrollable)target).Offset = new Vector(0, 11);
+////            ((ILogicalScrollable)target).Offset = new Vector(0, 11);
 
-            minIndex = target.ItemContainerGenerator.Containers.Min(x => x.Index);
-            Assert.Equal(new Vector(0, 11), ((ILogicalScrollable)target).Offset);
-            Assert.Equal(10, minIndex);
-            Assert.Equal(10, ((IVirtualizingPanel)target.Panel).PixelOffset);
-        }
+////            minIndex = target.ItemContainerGenerator.Containers.Min(x => x.Index);
+////            Assert.Equal(new Vector(0, 11), ((ILogicalScrollable)target).Offset);
+////            Assert.Equal(10, minIndex);
+////            Assert.Equal(10, ((IVirtualizingPanel)target.Panel).PixelOffset);
+////        }
 
-        [Fact]
-        public void Inserting_Items_Should_Update_Containers()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Inserting_Items_Should_Update_Containers()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            ((ILogicalScrollable)target).Offset = new Vector(0, 5);
+////            ((ILogicalScrollable)target).Offset = new Vector(0, 5);
 
-            var expected = Enumerable.Range(5, 10).Select(x => $"Item {x}").ToList();
-            var items = (ObservableCollection<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(5, 10).Select(x => $"Item {x}").ToList();
+////            var items = (ObservableCollection<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            items.Insert(6, "Inserted");
-            expected.Insert(1, "Inserted");
-            expected.RemoveAt(expected.Count - 1);
+////            items.Insert(6, "Inserted");
+////            expected.Insert(1, "Inserted");
+////            expected.RemoveAt(expected.Count - 1);
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Inserting_Items_Before_Visibile_Containers_Should_Update_Containers()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Inserting_Items_Before_Visibile_Containers_Should_Update_Containers()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            ((ILogicalScrollable)target).Offset = new Vector(0, 5);
+////            ((ILogicalScrollable)target).Offset = new Vector(0, 5);
 
-            var expected = Enumerable.Range(5, 10).Select(x => $"Item {x}").ToList();
-            var items = (ObservableCollection<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(5, 10).Select(x => $"Item {x}").ToList();
+////            var items = (ObservableCollection<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            items.Insert(0, "Inserted");
+////            items.Insert(0, "Inserted");
 
-            expected = Enumerable.Range(4, 10).Select(x => $"Item {x}").ToList();
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            expected = Enumerable.Range(4, 10).Select(x => $"Item {x}").ToList();
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Removing_First_Materialized_Item_Should_Update_Containers()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Removing_First_Materialized_Item_Should_Update_Containers()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
-            var items = (ObservableCollection<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
+////            var items = (ObservableCollection<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            items.RemoveAt(0);
-            expected = Enumerable.Range(1, 10).Select(x => $"Item {x}").ToList();
+////            items.RemoveAt(0);
+////            expected = Enumerable.Range(1, 10).Select(x => $"Item {x}").ToList();
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Removing_Items_From_Middle_Should_Update_Containers_When_All_Items_Visible()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Removing_Items_From_Middle_Should_Update_Containers_When_All_Items_Visible()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 200));
-            target.Arrange(new Rect(0, 0, 100, 200));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 200));
+////            target.Arrange(new Rect(0, 0, 100, 200));
 
-            var items = (ObservableCollection<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var items = (ObservableCollection<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(items, actual);
+////            Assert.Equal(items, actual);
 
-            items.RemoveAt(2);
+////            items.RemoveAt(2);
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(items, actual);
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(items, actual);
 
-            items.RemoveAt(items.Count - 2);
+////            items.RemoveAt(items.Count - 2);
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(items, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(items, actual);
+////        }
 
-        [Fact]
-        public void Removing_Last_Item_Should_Update_Containers_When_All_Items_Visible()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Removing_Last_Item_Should_Update_Containers_When_All_Items_Visible()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 200));
-            target.Arrange(new Rect(0, 0, 100, 200));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 200));
+////            target.Arrange(new Rect(0, 0, 100, 200));
 
-            ((ILogicalScrollable)target).Offset = new Vector(0, 5);
+////            ((ILogicalScrollable)target).Offset = new Vector(0, 5);
 
-            var expected = Enumerable.Range(0, 20).Select(x => $"Item {x}").ToList();
-            var items = (ObservableCollection<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 20).Select(x => $"Item {x}").ToList();
+////            var items = (ObservableCollection<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            items.Remove(items.Last());
-            expected.Remove(expected.Last());
+////            items.Remove(items.Last());
+////            expected.Remove(expected.Last());
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Removing_Items_When_Scrolled_To_End_Should_Recyle_Containers_At_Top()
-        {
-            var target = CreateTarget(useAvaloniaList: true);
+////        [Fact]
+////        public void Removing_Items_When_Scrolled_To_End_Should_Recyle_Containers_At_Top()
+////        {
+////            var target = CreateTarget(useAvaloniaList: true);
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            ((ILogicalScrollable)target).Offset = new Vector(0, 10);
+////            ((ILogicalScrollable)target).Offset = new Vector(0, 10);
 
-            var expected = Enumerable.Range(10, 10).Select(x => $"Item {x}").ToList();
-            var items = (AvaloniaList<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(10, 10).Select(x => $"Item {x}").ToList();
+////            var items = (AvaloniaList<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            items.RemoveRange(18, 2);
-            expected = Enumerable.Range(8, 10).Select(x => $"Item {x}").ToList();
+////            items.RemoveRange(18, 2);
+////            expected = Enumerable.Range(8, 10).Select(x => $"Item {x}").ToList();
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Removing_Items_When_Scrolled_To_Near_End_Should_Recycle_Containers_At_Bottom_And_Top()
-        {
-            var target = CreateTarget(useAvaloniaList: true);
+////        [Fact]
+////        public void Removing_Items_When_Scrolled_To_Near_End_Should_Recycle_Containers_At_Bottom_And_Top()
+////        {
+////            var target = CreateTarget(useAvaloniaList: true);
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            ((ILogicalScrollable)target).Offset = new Vector(0, 9);
+////            ((ILogicalScrollable)target).Offset = new Vector(0, 9);
 
-            var expected = Enumerable.Range(9, 10).Select(x => $"Item {x}").ToList();
-            var items = (AvaloniaList<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(9, 10).Select(x => $"Item {x}").ToList();
+////            var items = (AvaloniaList<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            items.RemoveRange(15, 3);
-            expected = Enumerable.Range(7, 8).Select(x => $"Item {x}")
-                .Concat(Enumerable.Range(18, 2).Select(x => $"Item {x}"))
-                .ToList();
+////            items.RemoveRange(15, 3);
+////            expected = Enumerable.Range(7, 8).Select(x => $"Item {x}")
+////                .Concat(Enumerable.Range(18, 2).Select(x => $"Item {x}"))
+////                .ToList();
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Measuring_To_Infinity_When_Scrolled_To_End_Should_Not_Throw()
-        {
-            var target = CreateTarget(useAvaloniaList: true);
+////        [Fact]
+////        public void Measuring_To_Infinity_When_Scrolled_To_End_Should_Not_Throw()
+////        {
+////            var target = CreateTarget(useAvaloniaList: true);
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            ((ILogicalScrollable)target).Offset = new Vector(0, 10);
+////            ((ILogicalScrollable)target).Offset = new Vector(0, 10);
 
-            // Check for issue #589: this should not throw.
-            target.Measure(Size.Infinity);
+////            // Check for issue #589: this should not throw.
+////            target.Measure(Size.Infinity);
 
-            var expected = Enumerable.Range(0, 20).Select(x => $"Item {x}").ToList();
-            var items = (AvaloniaList<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 20).Select(x => $"Item {x}").ToList();
+////            var items = (AvaloniaList<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
-        }
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Replacing_Items_Should_Update_Containers()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Replacing_Items_Should_Update_Containers()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
-            var items = (ObservableCollection<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
+////            var items = (ObservableCollection<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            items[4] = expected[4] = "Replaced";
+////            items[4] = expected[4] = "Replaced";
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Moving_Items_Should_Update_Containers()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Moving_Items_Should_Update_Containers()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
-            var items = (ObservableCollection<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
+////            var items = (ObservableCollection<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            items.Move(4, 8);
-            var i = expected[4];
-            expected.RemoveAt(4);
-            expected.Insert(8, i);
+////            items.Move(4, 8);
+////            var i = expected[4];
+////            expected.RemoveAt(4);
+////            expected.Insert(8, i);
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Setting_Items_To_Null_Should_Remove_Containers()
-        {
-            var target = CreateTarget();
+////        [Fact]
+////        public void Setting_Items_To_Null_Should_Remove_Containers()
+////        {
+////            var target = CreateTarget();
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
-            var items = (ObservableCollection<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
+////            var items = (ObservableCollection<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            target.Items = null;
+////            target.Items = null;
 
-            Assert.Empty(target.Panel.Children);
-        }
+////            Assert.Empty(target.Panel.Children);
+////        }
 
-        [Fact]
-        public void Reassigning_Items_Should_Create_Containers()
-        {
-            var target = CreateTarget(itemCount: 5);
+////        [Fact]
+////        public void Reassigning_Items_Should_Create_Containers()
+////        {
+////            var target = CreateTarget(itemCount: 5);
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 5).Select(x => $"Item {x}").ToList();
-            var items = (ObservableCollection<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 5).Select(x => $"Item {x}").ToList();
+////            var items = (ObservableCollection<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            expected = Enumerable.Range(0, 6).Select(x => $"Item {x}").ToList();
-            target.Items = expected;
+////            expected = Enumerable.Range(0, 6).Select(x => $"Item {x}").ToList();
+////            target.Items = expected;
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Inserting_Then_Removing_Should_Add_Remove_Containers()
-        {
-            var items = new AvaloniaList<string>(Enumerable.Range(0, 5).Select(x => $"Item {x}"));
-            var toAdd = Enumerable.Range(0, 3).Select(x => $"Added Item {x}").ToArray();
-            var target = new ItemsPresenter
-            {
-                VirtualizationMode = ItemVirtualizationMode.None,
-                Items = items,
-                ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Height = 10 }),
-            };
+////        [Fact]
+////        public void Inserting_Then_Removing_Should_Add_Remove_Containers()
+////        {
+////            var items = new AvaloniaList<string>(Enumerable.Range(0, 5).Select(x => $"Item {x}"));
+////            var toAdd = Enumerable.Range(0, 3).Select(x => $"Added Item {x}").ToArray();
+////            var target = new ItemsPresenter
+////            {
+////                VirtualizationMode = ItemVirtualizationMode.None,
+////                Items = items,
+////                ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Height = 10 }),
+////            };
 
-            target.ApplyTemplate();
+////            target.ApplyTemplate();
 
-            Assert.Equal(items.Count, target.Panel.Children.Count);
+////            Assert.Equal(items.Count, target.Panel.Children.Count);
 
-            int addIndex = 1;
-            foreach (var item in toAdd)
-            {
-                items.Insert(addIndex++, item);
-            }
+////            int addIndex = 1;
+////            foreach (var item in toAdd)
+////            {
+////                items.Insert(addIndex++, item);
+////            }
 
-            Assert.Equal(items.Count, target.Panel.Children.Count);
+////            Assert.Equal(items.Count, target.Panel.Children.Count);
 
-            foreach (var item in toAdd)
-            {
-                items.Remove(item);
-            }
-
-            Assert.Equal(items.Count, target.Panel.Children.Count);
-        }
-
-        [Fact]
-        public void Reassigning_Items_Should_Remove_Containers()
-        {
-            var target = CreateTarget(itemCount: 6);
+////            foreach (var item in toAdd)
+////            {
+////                items.Remove(item);
+////            }
+
+////            Assert.Equal(items.Count, target.Panel.Children.Count);
+////        }
+
+////        [Fact]
+////        public void Reassigning_Items_Should_Remove_Containers()
+////        {
+////            var target = CreateTarget(itemCount: 6);
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 6).Select(x => $"Item {x}").ToList();
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 6).Select(x => $"Item {x}").ToList();
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            expected = Enumerable.Range(0, 5).Select(x => $"Item {x}").ToList();
-            target.Items = expected;
+////            expected = Enumerable.Range(0, 5).Select(x => $"Item {x}").ToList();
+////            target.Items = expected;
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Clearing_Items_And_ReAdding_Should_Remove_Containers()
-        {
-            var target = CreateTarget(itemCount: 6);
+////        [Fact]
+////        public void Clearing_Items_And_ReAdding_Should_Remove_Containers()
+////        {
+////            var target = CreateTarget(itemCount: 6);
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 6).Select(x => $"Item {x}").ToList();
-            var items = (ObservableCollection<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 6).Select(x => $"Item {x}").ToList();
+////            var items = (ObservableCollection<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            expected = Enumerable.Range(0, 5).Select(x => $"Item {x}").ToList();
-            target.Items = null;
-            target.Items = expected;
+////            expected = Enumerable.Range(0, 5).Select(x => $"Item {x}").ToList();
+////            target.Items = null;
+////            target.Items = expected;
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Scrolling_To_Partial_Last_Item_Then_Adding_Item_Updates_Containers()
-        {
-            var target = CreateTarget(itemCount: 10);
-            var items = (IList<string>)target.Items;
+////        [Fact]
+////        public void Scrolling_To_Partial_Last_Item_Then_Adding_Item_Updates_Containers()
+////        {
+////            var target = CreateTarget(itemCount: 10);
+////            var items = (IList<string>)target.Items;
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 95));
-            target.Arrange(new Rect(0, 0, 100, 95));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 95));
+////            target.Arrange(new Rect(0, 0, 100, 95));
 
-            ((ILogicalScrollable)target).Offset = new Vector(0, 1);
-            Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
+////            ((ILogicalScrollable)target).Offset = new Vector(0, 1);
+////            Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
 
-            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-            Assert.Equal(10, ((IVirtualizingPanel)target.Panel).PixelOffset);
+////            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////            Assert.Equal(10, ((IVirtualizingPanel)target.Panel).PixelOffset);
 
-            items.Add("Item 10");
+////            items.Add("Item 10");
 
-            expected = Enumerable.Range(1, 10).Select(x => $"Item {x}").ToList();
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-            Assert.Equal(0, ((IVirtualizingPanel)target.Panel).PixelOffset);
-        }
+////            expected = Enumerable.Range(1, 10).Select(x => $"Item {x}").ToList();
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////            Assert.Equal(0, ((IVirtualizingPanel)target.Panel).PixelOffset);
+////        }
 
-        [Fact]
-        public void Scrolling_To_Item_In_Zero_Sized_Presenter_Doesnt_Throw()
-        {
-            using (UnitTestApplication.Start(new TestServices()))
-            {
-                var target = CreateTarget(itemCount: 10);
-                var items = (IList<string>)target.Items;
-                target.ApplyTemplate();
-                target.Measure(Size.Empty);
-                target.Arrange(Rect.Empty);
+////        [Fact]
+////        public void Scrolling_To_Item_In_Zero_Sized_Presenter_Doesnt_Throw()
+////        {
+////            using (UnitTestApplication.Start(new TestServices()))
+////            {
+////                var target = CreateTarget(itemCount: 10);
+////                var items = (IList<string>)target.Items;
+////                target.ApplyTemplate();
+////                target.Measure(Size.Empty);
+////                target.Arrange(Rect.Empty);
 
-                // Check for issue #591: this should not throw.
-                target.ScrollIntoView(0);
-            }
-        }
+////                // Check for issue #591: this should not throw.
+////                target.ScrollIntoView(0);
+////            }
+////        }
 
-        [Fact]
-        public void InsertRange_Items_Should_Update_Containers()
-        {
-            var target = CreateTarget(useAvaloniaList: true);
+////        [Fact]
+////        public void InsertRange_Items_Should_Update_Containers()
+////        {
+////            var target = CreateTarget(useAvaloniaList: true);
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
-            var items = (AvaloniaList<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
+////            var items = (AvaloniaList<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            var toAdd = Enumerable.Range(0, 3).Select(x => $"New Item {x}").ToList();
+////            var toAdd = Enumerable.Range(0, 3).Select(x => $"New Item {x}").ToList();
 
-            int index = 1;
+////            int index = 1;
 
-            items.InsertRange(index, toAdd);
-            expected.InsertRange(index, toAdd);
-            expected.RemoveRange(10, toAdd.Count);
+////            items.InsertRange(index, toAdd);
+////            expected.InsertRange(index, toAdd);
+////            expected.RemoveRange(10, toAdd.Count);
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void InsertRange_Items_Before_Last_Should_Update_Containers()
-        {
-            var target = CreateTarget(useAvaloniaList: true);
+////        [Fact]
+////        public void InsertRange_Items_Before_Last_Should_Update_Containers()
+////        {
+////            var target = CreateTarget(useAvaloniaList: true);
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
-            var items = (AvaloniaList<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
+////            var items = (AvaloniaList<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected, actual);
+////            Assert.Equal(expected, actual);
 
-            var toAdd = Enumerable.Range(0, 3).Select(x => $"New Item {x}").ToList();
+////            var toAdd = Enumerable.Range(0, 3).Select(x => $"New Item {x}").ToList();
 
-            int index = 8;
+////            int index = 8;
 
-            items.InsertRange(index, toAdd);
-            expected.InsertRange(index, toAdd);
-            expected.RemoveRange(10, toAdd.Count);
+////            items.InsertRange(index, toAdd);
+////            expected.InsertRange(index, toAdd);
+////            expected.RemoveRange(10, toAdd.Count);
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void RemoveRange_Items_Should_Update_Containers()
-        {
-            var target = CreateTarget(useAvaloniaList: true);
+////        [Fact]
+////        public void RemoveRange_Items_Should_Update_Containers()
+////        {
+////            var target = CreateTarget(useAvaloniaList: true);
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 13).Select(x => $"Item {x}").ToList();
-            var items = (AvaloniaList<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 13).Select(x => $"Item {x}").ToList();
+////            var items = (AvaloniaList<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected.Take(10), actual);
+////            Assert.Equal(expected.Take(10), actual);
 
-            int index = 5;
-            int count = 3;
+////            int index = 5;
+////            int count = 3;
 
-            items.RemoveRange(index, count);
-            expected.RemoveRange(index, count);
+////            items.RemoveRange(index, count);
+////            expected.RemoveRange(index, count);
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void RemoveRange_Items_Before_Last_Should_Update_Containers()
-        {
-            var target = CreateTarget(useAvaloniaList: true);
+////        [Fact]
+////        public void RemoveRange_Items_Before_Last_Should_Update_Containers()
+////        {
+////            var target = CreateTarget(useAvaloniaList: true);
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var expected = Enumerable.Range(0, 13).Select(x => $"Item {x}").ToList();
-            var items = (AvaloniaList<string>)target.Items;
-            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var expected = Enumerable.Range(0, 13).Select(x => $"Item {x}").ToList();
+////            var items = (AvaloniaList<string>)target.Items;
+////            var actual = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            Assert.Equal(expected.Take(10), actual);
+////            Assert.Equal(expected.Take(10), actual);
 
-            int index = 8;
-            int count = 3;
+////            int index = 8;
+////            int count = 3;
 
-            items.RemoveRange(index, count);
-            expected.RemoveRange(index, count);
+////            items.RemoveRange(index, count);
+////            expected.RemoveRange(index, count);
 
-            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
-            Assert.Equal(expected, actual);
-        }
+////            actual = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            Assert.Equal(expected, actual);
+////        }
 
-        [Fact]
-        public void Should_Add_Containers_For_Items_After_Clear()
-        {
-            var target = CreateTarget(itemCount: 10);
-            var defaultItems = (IList<string>)target.Items;
-            var items = new AvaloniaList<string>(defaultItems);
-            target.Items = items;
+////        [Fact]
+////        public void Should_Add_Containers_For_Items_After_Clear()
+////        {
+////            var target = CreateTarget(itemCount: 10);
+////            var defaultItems = (IList<string>)target.Items;
+////            var items = new AvaloniaList<string>(defaultItems);
+////            target.Items = items;
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(target.DesiredSize));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(target.DesiredSize));
 
-            Assert.Equal(10, target.Panel.Children.Count);
+////            Assert.Equal(10, target.Panel.Children.Count);
 
-            items.Clear();
+////            items.Clear();
 
-            target.Panel.Measure(new Size(100, 100));
-            target.Panel.Arrange(new Rect(target.Panel.DesiredSize));
+////            target.Panel.Measure(new Size(100, 100));
+////            target.Panel.Arrange(new Rect(target.Panel.DesiredSize));
 
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(target.DesiredSize));
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(target.DesiredSize));
 
-            Assert.Empty(target.Panel.Children);
+////            Assert.Empty(target.Panel.Children);
 
-            items.AddRange(defaultItems.Select(s => s + " new"));
+////            items.AddRange(defaultItems.Select(s => s + " new"));
 
-            target.Panel.Measure(new Size(100, 100));
-            target.Panel.Arrange(new Rect(target.Panel.DesiredSize));
+////            target.Panel.Measure(new Size(100, 100));
+////            target.Panel.Arrange(new Rect(target.Panel.DesiredSize));
 
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(target.DesiredSize));
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(target.DesiredSize));
 
-            Assert.Equal(10, target.Panel.Children.Count);
-        }
+////            Assert.Equal(10, target.Panel.Children.Count);
+////        }
 
-        [Fact]
-        public void Scroll_To_Last_Should_Work()
-        {
-            var target = CreateTarget(itemCount: 11);
-            var scroller = (TestScroller)target.Parent;
+////        [Fact]
+////        public void Scroll_To_Last_Should_Work()
+////        {
+////            var target = CreateTarget(itemCount: 11);
+////            var scroller = (TestScroller)target.Parent;
 
-            scroller.Width = scroller.Height = 100;
-            scroller.LayoutManager.ExecuteInitialLayoutPass();
+////            scroller.Width = scroller.Height = 100;
+////            scroller.LayoutManager.ExecuteInitialLayoutPass();
 
-            var last = (target.Items as IList)[10];
+////            var last = (target.Items as IList)[10];
 
-            target.ScrollIntoView(10);
+////            target.ScrollIntoView(10);
 
-            Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
-            Assert.Same(target.Panel.Children[9].DataContext, last);
-        }
+////            Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
+////            Assert.Same(target.Panel.Children[9].DataContext, last);
+////        }
 
-        [Fact]
-        public void Second_Scroll_To_Last_Should_Work()
-        {
-            var target = CreateTarget(itemCount: 11);
-            var scroller = (TestScroller)target.Parent;
+////        [Fact]
+////        public void Second_Scroll_To_Last_Should_Work()
+////        {
+////            var target = CreateTarget(itemCount: 11);
+////            var scroller = (TestScroller)target.Parent;
 
-            scroller.Width = scroller.Height = 100;
-            scroller.LayoutManager.ExecuteInitialLayoutPass();
+////            scroller.Width = scroller.Height = 100;
+////            scroller.LayoutManager.ExecuteInitialLayoutPass();
 
-            var last = (target.Items as IList)[10];
+////            var last = (target.Items as IList)[10];
 
-            target.ScrollIntoView(10);
+////            target.ScrollIntoView(10);
 
-            Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
-            Assert.Same(target.Panel.Children[9].DataContext, last);
+////            Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
+////            Assert.Same(target.Panel.Children[9].DataContext, last);
 
-            target.ScrollIntoView(10);
+////            target.ScrollIntoView(10);
 
-            Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
-            Assert.Same(target.Panel.Children[9].DataContext, last);
-        }
+////            Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
+////            Assert.Same(target.Panel.Children[9].DataContext, last);
+////        }
 
-        [Fact]
-        public void Scrolling_Less_Than_A_Page_Should_Move_Recycled_Items()
-        {
-            var target = CreateTarget();
-            var items = (IList<string>)target.Items;
+////        [Fact]
+////        public void Scrolling_Less_Than_A_Page_Should_Move_Recycled_Items()
+////        {
+////            var target = CreateTarget();
+////            var items = (IList<string>)target.Items;
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var containers = target.Panel.Children.ToList();
-            var scroller = (ScrollContentPresenter)target.Parent;
+////            var containers = target.Panel.Children.ToList();
+////            var scroller = (ScrollContentPresenter)target.Parent;
 
-            scroller.Offset = new Vector(0, 5);
+////            scroller.Offset = new Vector(0, 5);
 
-            var scrolledContainers = containers
-                .Skip(5)
-                .Take(5)
-                .Concat(containers.Take(5)).ToList();
+////            var scrolledContainers = containers
+////                .Skip(5)
+////                .Take(5)
+////                .Concat(containers.Take(5)).ToList();
 
-            Assert.Equal(new Vector(0, 5), ((ILogicalScrollable)target).Offset);
-            Assert.Equal(scrolledContainers, target.Panel.Children);
+////            Assert.Equal(new Vector(0, 5), ((ILogicalScrollable)target).Offset);
+////            Assert.Equal(scrolledContainers, target.Panel.Children);
 
-            for (var i = 0; i < target.Panel.Children.Count; ++i)
-            {
-                Assert.Equal(items[i + 5], target.Panel.Children[i].DataContext);
-            }
+////            for (var i = 0; i < target.Panel.Children.Count; ++i)
+////            {
+////                Assert.Equal(items[i + 5], target.Panel.Children[i].DataContext);
+////            }
 
-            scroller.Offset = new Vector(0, 0);
-            Assert.Equal(new Vector(0, 0), ((ILogicalScrollable)target).Offset);
-            Assert.Equal(containers, target.Panel.Children);
+////            scroller.Offset = new Vector(0, 0);
+////            Assert.Equal(new Vector(0, 0), ((ILogicalScrollable)target).Offset);
+////            Assert.Equal(containers, target.Panel.Children);
 
-            var dcs = target.Panel.Children.Select(x => x.DataContext).ToList();
+////            var dcs = target.Panel.Children.Select(x => x.DataContext).ToList();
 
-            for (var i = 0; i < target.Panel.Children.Count; ++i)
-            {
-                Assert.Equal(items[i], target.Panel.Children[i].DataContext);
-            }
-        }
+////            for (var i = 0; i < target.Panel.Children.Count; ++i)
+////            {
+////                Assert.Equal(items[i], target.Panel.Children[i].DataContext);
+////            }
+////        }
 
-        [Fact]
-        public void Scrolling_More_Than_A_Page_Should_Recycle_Items()
-        {
-            var target = CreateTarget(itemCount: 50);
-            var items = (IList<string>)target.Items;
+////        [Fact]
+////        public void Scrolling_More_Than_A_Page_Should_Recycle_Items()
+////        {
+////            var target = CreateTarget(itemCount: 50);
+////            var items = (IList<string>)target.Items;
 
-            target.ApplyTemplate();
-            target.Measure(new Size(100, 100));
-            target.Arrange(new Rect(0, 0, 100, 100));
+////            target.ApplyTemplate();
+////            target.Measure(new Size(100, 100));
+////            target.Arrange(new Rect(0, 0, 100, 100));
 
-            var containers = target.Panel.Children.ToList();
-            var scroller = (ScrollContentPresenter)target.Parent;
+////            var containers = target.Panel.Children.ToList();
+////            var scroller = (ScrollContentPresenter)target.Parent;
 
-            scroller.Offset = new Vector(0, 20);
+////            scroller.Offset = new Vector(0, 20);
 
-            Assert.Equal(new Vector(0, 20), ((ILogicalScrollable)target).Offset);
-            Assert.Equal(containers, target.Panel.Children);
+////            Assert.Equal(new Vector(0, 20), ((ILogicalScrollable)target).Offset);
+////            Assert.Equal(containers, target.Panel.Children);
 
-            for (var i = 0; i < target.Panel.Children.Count; ++i)
-            {
-                Assert.Equal(items[i + 20], target.Panel.Children[i].DataContext);
-            }
+////            for (var i = 0; i < target.Panel.Children.Count; ++i)
+////            {
+////                Assert.Equal(items[i + 20], target.Panel.Children[i].DataContext);
+////            }
 
-            scroller.Offset = new Vector(0, 0);
+////            scroller.Offset = new Vector(0, 0);
 
-            Assert.Equal(new Vector(0, 0), ((ILogicalScrollable)target).Offset);
-            Assert.Equal(containers, target.Panel.Children);
+////            Assert.Equal(new Vector(0, 0), ((ILogicalScrollable)target).Offset);
+////            Assert.Equal(containers, target.Panel.Children);
 
-            for (var i = 0; i < target.Panel.Children.Count; ++i)
-            {
-                Assert.Equal(items[i], target.Panel.Children[i].DataContext);
-            }
-        }
+////            for (var i = 0; i < target.Panel.Children.Count; ++i)
+////            {
+////                Assert.Equal(items[i], target.Panel.Children[i].DataContext);
+////            }
+////        }
 
-        public class Vertical
-        {
-            [Fact]
-            public void GetControlInDirection_Down_Should_Return_Existing_Container_If_Materialized()
-            {
-                var target = CreateTarget();
-                var scroller = (TestScroller)target.Parent;
+////        public class Vertical
+////        {
+////            [Fact]
+////            public void GetControlInDirection_Down_Should_Return_Existing_Container_If_Materialized()
+////            {
+////                var target = CreateTarget();
+////                var scroller = (TestScroller)target.Parent;
 
-                scroller.Width = scroller.Height = 100;
-                scroller.LayoutManager.ExecuteInitialLayoutPass();
+////                scroller.Width = scroller.Height = 100;
+////                scroller.LayoutManager.ExecuteInitialLayoutPass();
 
-                var from = target.Panel.Children[5];
-                var result = ((ILogicalScrollable)target).GetControlInDirection(
-                    NavigationDirection.Down,
-                    from);
-
-                Assert.Same(target.Panel.Children[6], result);
-            }
-
-            [Fact]
-            public void GetControlInDirection_Down_Should_Scroll_If_Necessary()
-            {
-                var target = CreateTarget();
-                var scroller = (TestScroller)target.Parent;
-
-                scroller.Width = scroller.Height = 100;
-                scroller.LayoutManager.ExecuteInitialLayoutPass();
-
-                var from = target.Panel.Children[9];
-                var result = ((ILogicalScrollable)target).GetControlInDirection(
-                    NavigationDirection.Down,
-                    from);
-
-                Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
-                Assert.Same(target.Panel.Children[9], result);
-            }
-
-            [Fact]
-            public void GetControlInDirection_Down_Should_Scroll_If_Partially_Visible()
-            {
-                var target = CreateTarget();
-                var scroller = (TestScroller)target.Parent;
-
-                scroller.Width = 100;
-                scroller.Height = 95;
-                scroller.LayoutManager.ExecuteInitialLayoutPass();
-
-                var from = target.Panel.Children[8];
-                var result = ((ILogicalScrollable)target).GetControlInDirection(
-                    NavigationDirection.Down,
-                    from);
-
-                Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
-                Assert.Same(target.Panel.Children[8], result);
-            }
-
-            [Fact]
-            public void GetControlInDirection_Up_Should_Scroll_If_Partially_Visible_Item_Is_Currently_Shown()
-            {
-                var target = CreateTarget();
-                var scroller = (TestScroller)target.Parent;
-
-                scroller.Width = 100;
-                scroller.Height = 95;
-                scroller.LayoutManager.ExecuteInitialLayoutPass();
-                ((ILogicalScrollable)target).Offset = new Vector(0, 11);
-
-                var from = target.Panel.Children[1];
-                var result = ((ILogicalScrollable)target).GetControlInDirection(
-                    NavigationDirection.Up,
-                    from);
-
-                Assert.Equal(new Vector(0, 10), ((ILogicalScrollable)target).Offset);
-                Assert.Same(target.Panel.Children[0], result);
-            }
-
-            [Fact]
-            public void Should_Return_Horizontal_Extent_And_Viewport()
-            {
-                var target = CreateTarget();
-
-                target.ApplyTemplate();
-                target.Measure(new Size(5, 100));
-                target.Arrange(new Rect(0, 0, 5, 100));
-
-                Assert.Equal(new Size(10, 20), ((ILogicalScrollable)target).Extent);
-                Assert.Equal(new Size(5, 10), ((ILogicalScrollable)target).Viewport);
-            }
-
-            [Fact]
-            public void Horizontal_Scroll_Should_Update_Item_Position()
-            {
-                var target = CreateTarget();
-
-                target.ApplyTemplate();
-
-                target.Measure(new Size(5, 100));
-                target.Arrange(new Rect(0, 0, 5, 100));
-
-                ((ILogicalScrollable)target).Offset = new Vector(5, 0);
-
-                target.Measure(new Size(5, 100));
-                target.Arrange(new Rect(0, 0, 5, 100));
-
-                Assert.Equal(new Rect(-5, 0, 10, 10), target.Panel.Children[0].Bounds);
-            }
-        }
-
-        public class Horizontal
-        {
-            [Fact]
-            public void GetControlInDirection_Right_Should_Return_Existing_Container_If_Materialized()
-            {
-                var target = CreateTarget(orientation: Orientation.Horizontal);
-                var scroller = (TestScroller)target.Parent;
-
-                scroller.Width = scroller.Height = 100;
-                scroller.LayoutManager.ExecuteInitialLayoutPass();
-
-                var from = target.Panel.Children[5];
-                var result = ((ILogicalScrollable)target).GetControlInDirection(
-                    NavigationDirection.Right,
-                    from);
-
-                Assert.Same(target.Panel.Children[6], result);
-            }
-
-            [Fact]
-            public void GetControlInDirection_Right_Should_Scroll_If_Necessary()
-            {
-                var target = CreateTarget(orientation: Orientation.Horizontal);
-                var scroller = (TestScroller)target.Parent;
-
-                scroller.Width = scroller.Height = 100;
-                scroller.LayoutManager.ExecuteInitialLayoutPass();
-
-                var from = target.Panel.Children[9];
-                var result = ((ILogicalScrollable)target).GetControlInDirection(
-                    NavigationDirection.Right,
-                    from);
-
-                Assert.Equal(new Vector(1, 0), ((ILogicalScrollable)target).Offset);
-                Assert.Same(target.Panel.Children[9], result);
-            }
-
-            [Fact]
-            public void GetControlInDirection_Right_Should_Scroll_If_Partially_Visible()
-            {
-                var target = CreateTarget(orientation: Orientation.Horizontal);
-                var scroller = (TestScroller)target.Parent;
-
-                scroller.Width = 95;
-                scroller.Height = 100;
-                scroller.LayoutManager.ExecuteInitialLayoutPass();
-
-                var from = target.Panel.Children[8];
-                var result = ((ILogicalScrollable)target).GetControlInDirection(
-                    NavigationDirection.Right,
-                    from);
-
-                Assert.Equal(new Vector(1, 0), ((ILogicalScrollable)target).Offset);
-                Assert.Same(target.Panel.Children[8], result);
-            }
-
-            [Fact]
-            public void GetControlInDirection_Left_Should_Scroll_If_Partially_Visible_Item_Is_Currently_Shown()
-            {
-                var target = CreateTarget(orientation: Orientation.Horizontal);
-                var scroller = (TestScroller)target.Parent;
-
-                scroller.Width = 95;
-                scroller.Height = 100;
-                scroller.LayoutManager.ExecuteInitialLayoutPass();
-                ((ILogicalScrollable)target).Offset = new Vector(11, 0);
-
-                var from = target.Panel.Children[1];
-                var result = ((ILogicalScrollable)target).GetControlInDirection(
-                    NavigationDirection.Left,
-                    from);
-
-                Assert.Equal(new Vector(10, 0), ((ILogicalScrollable)target).Offset);
-                Assert.Same(target.Panel.Children[0], result);
-            }
-        }
-
-        private static ItemsPresenter CreateTarget(
-            Orientation orientation = Orientation.Vertical,
-            int itemCount = 20,
-            bool useAvaloniaList = false)
-        {
-            ItemsPresenter result;
-            var itemsSource = Enumerable.Range(0, itemCount).Select(x => $"Item {x}");
-            var items = useAvaloniaList ?
-                (IEnumerable)new AvaloniaList<string>(itemsSource) :
-                (IEnumerable)new ObservableCollection<string>(itemsSource);
-
-            var scroller = new TestScroller
-            {
-                CanHorizontallyScroll = true,
-                CanVerticallyScroll = true,
-                Content = result = new TestItemsPresenter
-                {
-                    Items = items,
-                    ItemsPanel = VirtualizingPanelTemplate(orientation),
-                    DataTemplates = { StringDataTemplate() },
-                    VirtualizationMode = ItemVirtualizationMode.Simple,
-                }
-            };
-
-            scroller.UpdateChild();
-            return result;
-        }
-
-        private static IDataTemplate StringDataTemplate()
-        {
-            return new FuncDataTemplate<string>((x, _) => new Canvas
-            {
-                Width = 10,
-                Height = 10,
-            });
-        }
-
-        private static ITemplate<Panel> VirtualizingPanelTemplate(
-            Orientation orientation = Orientation.Vertical)
-        {
-            return new FuncTemplate<Panel>(() => new VirtualizingStackPanel
-            {
-                Orientation = orientation,
-            });
-        }
-
-        private class TestScroller : ScrollContentPresenter, IRenderRoot, ILayoutRoot, ILogicalRoot
-        {
-            public TestScroller()
-            {
-                LayoutManager = new LayoutManager(this);
-            }
-
-            public IRenderer Renderer { get; }
-            public Size ClientSize { get; }
-            public double RenderScaling => 1;
-
-            public Size MaxClientSize => Size.Infinity;
-
-            public double LayoutScaling => 1;
-
-            public ILayoutManager LayoutManager { get; }
-
-            public IRenderTarget CreateRenderTarget() => throw new NotImplementedException();
-            public void Invalidate(Rect rect) => throw new NotImplementedException();
-            public Point PointToClient(PixelPoint p) => throw new NotImplementedException();
-            public PixelPoint PointToScreen(Point p) => throw new NotImplementedException();
-        }
-
-        private class TestItemsPresenter : ItemsPresenter
-        {
-            protected override IItemContainerGenerator CreateItemContainerGenerator()
-            {
-                return new ItemContainerGenerator<TestContainer>(
-                    this,
-                    TestContainer.ContentProperty,
-                    null);
-            }
-        }
-
-        private class TestContainer : ContentControl
-        {
-            public TestContainer()
-            {
-                Template = new FuncControlTemplate<TestContainer>((parent, scope) => new ContentPresenter
-                {
-                    Name = "PART_ContentPresenter",
-                    [~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty],
-                    [~ContentPresenter.ContentTemplateProperty] = parent[~ContentControl.ContentTemplateProperty],
-                }.RegisterInNameScope(scope));
-            }
-        }
-    }
-}
+////                var from = target.Panel.Children[5];
+////                var result = ((ILogicalScrollable)target).GetControlInDirection(
+////                    NavigationDirection.Down,
+////                    from);
+
+////                Assert.Same(target.Panel.Children[6], result);
+////            }
+
+////            [Fact]
+////            public void GetControlInDirection_Down_Should_Scroll_If_Necessary()
+////            {
+////                var target = CreateTarget();
+////                var scroller = (TestScroller)target.Parent;
+
+////                scroller.Width = scroller.Height = 100;
+////                scroller.LayoutManager.ExecuteInitialLayoutPass();
+
+////                var from = target.Panel.Children[9];
+////                var result = ((ILogicalScrollable)target).GetControlInDirection(
+////                    NavigationDirection.Down,
+////                    from);
+
+////                Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
+////                Assert.Same(target.Panel.Children[9], result);
+////            }
+
+////            [Fact]
+////            public void GetControlInDirection_Down_Should_Scroll_If_Partially_Visible()
+////            {
+////                var target = CreateTarget();
+////                var scroller = (TestScroller)target.Parent;
+
+////                scroller.Width = 100;
+////                scroller.Height = 95;
+////                scroller.LayoutManager.ExecuteInitialLayoutPass();
+
+////                var from = target.Panel.Children[8];
+////                var result = ((ILogicalScrollable)target).GetControlInDirection(
+////                    NavigationDirection.Down,
+////                    from);
+
+////                Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset);
+////                Assert.Same(target.Panel.Children[8], result);
+////            }
+
+////            [Fact]
+////            public void GetControlInDirection_Up_Should_Scroll_If_Partially_Visible_Item_Is_Currently_Shown()
+////            {
+////                var target = CreateTarget();
+////                var scroller = (TestScroller)target.Parent;
+
+////                scroller.Width = 100;
+////                scroller.Height = 95;
+////                scroller.LayoutManager.ExecuteInitialLayoutPass();
+////                ((ILogicalScrollable)target).Offset = new Vector(0, 11);
+
+////                var from = target.Panel.Children[1];
+////                var result = ((ILogicalScrollable)target).GetControlInDirection(
+////                    NavigationDirection.Up,
+////                    from);
+
+////                Assert.Equal(new Vector(0, 10), ((ILogicalScrollable)target).Offset);
+////                Assert.Same(target.Panel.Children[0], result);
+////            }
+
+////            [Fact]
+////            public void Should_Return_Horizontal_Extent_And_Viewport()
+////            {
+////                var target = CreateTarget();
+
+////                target.ApplyTemplate();
+////                target.Measure(new Size(5, 100));
+////                target.Arrange(new Rect(0, 0, 5, 100));
+
+////                Assert.Equal(new Size(10, 20), ((ILogicalScrollable)target).Extent);
+////                Assert.Equal(new Size(5, 10), ((ILogicalScrollable)target).Viewport);
+////            }
+
+////            [Fact]
+////            public void Horizontal_Scroll_Should_Update_Item_Position()
+////            {
+////                var target = CreateTarget();
+
+////                target.ApplyTemplate();
+
+////                target.Measure(new Size(5, 100));
+////                target.Arrange(new Rect(0, 0, 5, 100));
+
+////                ((ILogicalScrollable)target).Offset = new Vector(5, 0);
+
+////                target.Measure(new Size(5, 100));
+////                target.Arrange(new Rect(0, 0, 5, 100));
+
+////                Assert.Equal(new Rect(-5, 0, 10, 10), target.Panel.Children[0].Bounds);
+////            }
+////        }
+
+////        public class Horizontal
+////        {
+////            [Fact]
+////            public void GetControlInDirection_Right_Should_Return_Existing_Container_If_Materialized()
+////            {
+////                var target = CreateTarget(orientation: Orientation.Horizontal);
+////                var scroller = (TestScroller)target.Parent;
+
+////                scroller.Width = scroller.Height = 100;
+////                scroller.LayoutManager.ExecuteInitialLayoutPass();
+
+////                var from = target.Panel.Children[5];
+////                var result = ((ILogicalScrollable)target).GetControlInDirection(
+////                    NavigationDirection.Right,
+////                    from);
+
+////                Assert.Same(target.Panel.Children[6], result);
+////            }
+
+////            [Fact]
+////            public void GetControlInDirection_Right_Should_Scroll_If_Necessary()
+////            {
+////                var target = CreateTarget(orientation: Orientation.Horizontal);
+////                var scroller = (TestScroller)target.Parent;
+
+////                scroller.Width = scroller.Height = 100;
+////                scroller.LayoutManager.ExecuteInitialLayoutPass();
+
+////                var from = target.Panel.Children[9];
+////                var result = ((ILogicalScrollable)target).GetControlInDirection(
+////                    NavigationDirection.Right,
+////                    from);
+
+////                Assert.Equal(new Vector(1, 0), ((ILogicalScrollable)target).Offset);
+////                Assert.Same(target.Panel.Children[9], result);
+////            }
+
+////            [Fact]
+////            public void GetControlInDirection_Right_Should_Scroll_If_Partially_Visible()
+////            {
+////                var target = CreateTarget(orientation: Orientation.Horizontal);
+////                var scroller = (TestScroller)target.Parent;
+
+////                scroller.Width = 95;
+////                scroller.Height = 100;
+////                scroller.LayoutManager.ExecuteInitialLayoutPass();
+
+////                var from = target.Panel.Children[8];
+////                var result = ((ILogicalScrollable)target).GetControlInDirection(
+////                    NavigationDirection.Right,
+////                    from);
+
+////                Assert.Equal(new Vector(1, 0), ((ILogicalScrollable)target).Offset);
+////                Assert.Same(target.Panel.Children[8], result);
+////            }
+
+////            [Fact]
+////            public void GetControlInDirection_Left_Should_Scroll_If_Partially_Visible_Item_Is_Currently_Shown()
+////            {
+////                var target = CreateTarget(orientation: Orientation.Horizontal);
+////                var scroller = (TestScroller)target.Parent;
+
+////                scroller.Width = 95;
+////                scroller.Height = 100;
+////                scroller.LayoutManager.ExecuteInitialLayoutPass();
+////                ((ILogicalScrollable)target).Offset = new Vector(11, 0);
+
+////                var from = target.Panel.Children[1];
+////                var result = ((ILogicalScrollable)target).GetControlInDirection(
+////                    NavigationDirection.Left,
+////                    from);
+
+////                Assert.Equal(new Vector(10, 0), ((ILogicalScrollable)target).Offset);
+////                Assert.Same(target.Panel.Children[0], result);
+////            }
+////        }
+
+////        private static ItemsPresenter CreateTarget(
+////            Orientation orientation = Orientation.Vertical,
+////            int itemCount = 20,
+////            bool useAvaloniaList = false)
+////        {
+////            ItemsPresenter result;
+////            var itemsSource = Enumerable.Range(0, itemCount).Select(x => $"Item {x}");
+////            var items = useAvaloniaList ?
+////                (IEnumerable)new AvaloniaList<string>(itemsSource) :
+////                (IEnumerable)new ObservableCollection<string>(itemsSource);
+
+////            var scroller = new TestScroller
+////            {
+////                CanHorizontallyScroll = true,
+////                CanVerticallyScroll = true,
+////                Content = result = new TestItemsPresenter
+////                {
+////                    Items = items,
+////                    ItemsPanel = VirtualizingPanelTemplate(orientation),
+////                    DataTemplates = { StringDataTemplate() },
+////                    VirtualizationMode = ItemVirtualizationMode.Simple,
+////                }
+////            };
+
+////            scroller.UpdateChild();
+////            return result;
+////        }
+
+////        private static IDataTemplate StringDataTemplate()
+////        {
+////            return new FuncDataTemplate<string>((x, _) => new Canvas
+////            {
+////                Width = 10,
+////                Height = 10,
+////            });
+////        }
+
+////        private static ITemplate<Panel> VirtualizingPanelTemplate(
+////            Orientation orientation = Orientation.Vertical)
+////        {
+////            return new FuncTemplate<Panel>(() => new VirtualizingStackPanel
+////            {
+////                Orientation = orientation,
+////            });
+////        }
+
+////        private class TestScroller : ScrollContentPresenter, IRenderRoot, ILayoutRoot, ILogicalRoot
+////        {
+////            public TestScroller()
+////            {
+////                LayoutManager = new LayoutManager(this);
+////            }
+
+////            public IRenderer Renderer { get; }
+////            public Size ClientSize { get; }
+////            public double RenderScaling => 1;
+
+////            public Size MaxClientSize => Size.Infinity;
+
+////            public double LayoutScaling => 1;
+
+////            public ILayoutManager LayoutManager { get; }
+
+////            public IRenderTarget CreateRenderTarget() => throw new NotImplementedException();
+////            public void Invalidate(Rect rect) => throw new NotImplementedException();
+////            public Point PointToClient(PixelPoint p) => throw new NotImplementedException();
+////            public PixelPoint PointToScreen(Point p) => throw new NotImplementedException();
+////        }
+
+////        private class TestItemsPresenter : ItemsPresenter
+////        {
+////            protected override IItemContainerGenerator CreateItemContainerGenerator()
+////            {
+////                return new ItemContainerGenerator<TestContainer>(
+////                    this,
+////                    TestContainer.ContentProperty,
+////                    null);
+////            }
+////        }
+
+////        private class TestContainer : ContentControl
+////        {
+////            public TestContainer()
+////            {
+////                Template = new FuncControlTemplate<TestContainer>((parent, scope) => new ContentPresenter
+////                {
+////                    Name = "PART_ContentPresenter",
+////                    [~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty],
+////                    [~ContentPresenter.ContentTemplateProperty] = parent[~ContentControl.ContentTemplateProperty],
+////                }.RegisterInNameScope(scope));
+////            }
+////        }
+////    }
+////}

+ 1 - 4
tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs

@@ -1115,10 +1115,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
             {
                 Name = "popup",
                 PlacementTarget = control,
-                Child = new ItemsPresenter
-                {
-                    [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
-                }
+                Child = new ItemsPresenter(),
             }.RegisterInNameScope(scope);
         }
 

+ 0 - 2
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs

@@ -2090,9 +2090,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
                 new ItemsPresenter
                 {
                     Name = "itemsPresenter",
-                    [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
                     [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
-                    [~ItemsPresenter.VirtualizationModeProperty] = control[~ListBox.VirtualizationModeProperty],
                 }.RegisterInNameScope(scope));
         }
 

+ 0 - 1
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs

@@ -125,7 +125,6 @@ namespace Avalonia.Controls.UnitTests.Primitives
                 new ItemsPresenter
                 {
                     Name = "itemsPresenter",
-                    [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
                     [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
                 }.RegisterInNameScope(scope));
         }

+ 0 - 1
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs

@@ -1536,7 +1536,6 @@ namespace Avalonia.Controls.UnitTests.Primitives
                 new ItemsPresenter
                 {
                     Name = "PART_ItemsPresenter",
-                    [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
                     [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
                 }.RegisterInNameScope(scope));
         }

+ 0 - 1
tests/Avalonia.Controls.UnitTests/Primitives/TabStripTests.cs

@@ -106,7 +106,6 @@ namespace Avalonia.Controls.UnitTests.Primitives
             return new ItemsPresenter
             {
                 Name = "itemsPresenter",
-                [!ItemsPresenter.ItemsProperty] = parent[!ItemsControl.ItemsProperty],
             }.RegisterInNameScope(scope);
         }
     }

+ 0 - 2
tests/Avalonia.Controls.UnitTests/TreeViewTests.cs

@@ -1303,7 +1303,6 @@ namespace Avalonia.Controls.UnitTests
             return new FuncControlTemplate<TreeView>((parent, scope) => new ItemsPresenter
             {
                 Name = "PART_ItemsPresenter",
-                [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
             }.RegisterInNameScope(scope));
         }
 
@@ -1321,7 +1320,6 @@ namespace Avalonia.Controls.UnitTests
                     new ItemsPresenter
                     {
                         Name = "PART_ItemsPresenter",
-                        [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
                     }.RegisterInNameScope(scope)
                 }
             });

+ 261 - 261
tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs

@@ -1,261 +1,261 @@
-using System;
-using System.Collections.Generic;
-using Avalonia.Controls.Primitives;
-using Avalonia.Input;
-using Avalonia.LogicalTree;
-using Moq;
-using Xunit;
-
-namespace Avalonia.Controls.UnitTests
-{
-    public class VirtualizingStackPanelTests
-    {
-        public class Vertical
-        {
-            [Fact]
-            public void Measure_Invokes_Controller_UpdateControls()
-            {
-                var target = new VirtualizingStackPanel();
-                var controller = new Mock<IVirtualizingController>();
-
-                ((IVirtualizingPanel)target).Controller = controller.Object;
-                target.Measure(new Size(100, 100));
-
-                controller.Verify(x => x.UpdateControls(), Times.Once());
-            }
-
-            [Fact]
-            public void Measure_Invokes_Controller_UpdateControls_If_AvailableSize_Changes()
-            {
-                var target = new VirtualizingStackPanel();
-                var controller = new Mock<IVirtualizingController>();
-
-                ((IVirtualizingPanel)target).Controller = controller.Object;
-                target.Measure(new Size(100, 100));
-                target.InvalidateMeasure();
-                target.Measure(new Size(100, 100));
-                target.InvalidateMeasure();
-                target.Measure(new Size(100, 101));
-
-                controller.Verify(x => x.UpdateControls(), Times.Exactly(2));
-            }
-
-            [Fact]
-            public void Measure_Does_Not_Invoke_Controller_UpdateControls_If_AvailableSize_Is_The_Same()
-            {
-                var target = new VirtualizingStackPanel();
-                var controller = new Mock<IVirtualizingController>();
-
-                ((IVirtualizingPanel)target).Controller = controller.Object;
-                target.Measure(new Size(100, 100));
-                target.InvalidateMeasure();
-                target.Measure(new Size(100, 100));
-
-                controller.Verify(x => x.UpdateControls(), Times.Once());
-            }
-
-            [Fact]
-            public void Measure_Invokes_Controller_UpdateControls_If_AvailableSize_Is_The_Same_After_ForceInvalidateMeasure()
-            {
-                var target = new VirtualizingStackPanel();
-                var controller = new Mock<IVirtualizingController>();
-
-                ((IVirtualizingPanel)target).Controller = controller.Object;
-                target.Measure(new Size(100, 100));
-                ((IVirtualizingPanel)target).ForceInvalidateMeasure();
-                target.Measure(new Size(100, 100));
-
-                controller.Verify(x => x.UpdateControls(), Times.Exactly(2));
-            }
-
-            [Fact]
-            public void Arrange_Invokes_Controller_UpdateControls()
-            {
-                var target = new VirtualizingStackPanel();
-                var controller = new Mock<IVirtualizingController>();
-
-                ((IVirtualizingPanel)target).Controller = controller.Object;
-                target.Measure(new Size(100, 100));
-                target.Arrange(new Rect(0, 0, 110, 110));
-
-                controller.Verify(x => x.UpdateControls(), Times.Exactly(2));
-            }
-
-            [Fact]
-            public void Reports_IsFull_False_Until_Measure_Height_Is_Reached()
-            {
-                var target = new VirtualizingStackPanel();
-                var vp = (IVirtualizingPanel)target;
-
-                target.Measure(new Size(100, 100));
-
-                Assert.Equal(new Size(0, 0), target.DesiredSize);
-                Assert.Equal(new Size(0, 0), target.Bounds.Size);
-
-                Assert.False(vp.IsFull);
-                Assert.Equal(0, vp.OverflowCount);
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                Assert.False(vp.IsFull);
-                Assert.Equal(0, vp.OverflowCount);
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                Assert.True(vp.IsFull);
-                Assert.Equal(0, vp.OverflowCount);
-            }
-
-            [Fact]
-            public void Reports_Overflow_After_Arrange()
-            {
-                var target = new VirtualizingStackPanel();
-                var vp = (IVirtualizingPanel)target;
-
-                target.Measure(new Size(100, 100));
-                target.Arrange(new Rect(target.DesiredSize));
-
-                Assert.Equal(new Size(0, 0), target.Bounds.Size);
-
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                Assert.Equal(0, vp.OverflowCount);
-
-                target.Measure(new Size(100, 100));
-                target.Arrange(new Rect(target.DesiredSize));
-
-                Assert.Equal(2, vp.OverflowCount);
-            }
-
-            [Fact]
-            public void Reports_Correct_Overflow_During_Arrange()
-            {
-                var target = new VirtualizingStackPanel();
-                var vp = (IVirtualizingPanel)target;
-                var controller = new Mock<IVirtualizingController>();
-                var called = false;
-
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                target.Children.Add(new Canvas { Width = 50, Height = 52 });
-                target.Measure(new Size(100, 100));
-
-                controller.Setup(x => x.UpdateControls()).Callback(() =>
-                {
-                    Assert.Equal(2, vp.PixelOverflow);
-                    Assert.Equal(0, vp.OverflowCount);
-                    called = true;
-                });
-
-                vp.Controller = controller.Object;
-                target.Arrange(new Rect(target.DesiredSize));
-
-                Assert.True(called);
-            }
-
-            [Fact]
-            public void Reports_PixelOverflow_After_Arrange()
-            {
-                var target = new VirtualizingStackPanel();
-
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                target.Children.Add(new Canvas { Width = 50, Height = 52 });
-
-                target.Measure(new Size(100, 100));
-                target.Arrange(new Rect(target.DesiredSize));
-
-                Assert.Equal(2, ((IVirtualizingPanel)target).PixelOverflow);
-            }
-
-            [Fact]
-            public void Reports_PixelOverflow_After_Arrange_Smaller_Than_Measure()
-            {
-                var target = new VirtualizingStackPanel();
-
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                target.Children.Add(new Canvas { Width = 50, Height = 52 });
-
-                target.Measure(new Size(100, 100));
-                target.Arrange(new Rect(0, 0, 50, 50));
-
-                Assert.Equal(52, ((IVirtualizingPanel)target).PixelOverflow);
-            }
-
-            [Fact]
-            public void Reports_PixelOverflow_With_PixelOffset()
-            {
-                var target = new VirtualizingStackPanel();
-                var vp = (IVirtualizingPanel)target;
-
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                target.Children.Add(new Canvas { Width = 50, Height = 52 });
-                vp.PixelOffset = 2;
-
-                target.Measure(new Size(100, 100));
-                target.Arrange(new Rect(target.DesiredSize));
-
-                Assert.Equal(2, vp.PixelOverflow);
-            }
-
-            [Fact]
-            public void PixelOffset_Can_Be_More_Than_Child_Without_Affecting_IsFull()
-            {
-                var target = new VirtualizingStackPanel();
-                var vp = (IVirtualizingPanel)target;
-
-                target.Children.Add(new Canvas { Width = 50, Height = 50 });
-                target.Children.Add(new Canvas { Width = 50, Height = 52 });
-                vp.PixelOffset = 55;
-
-                target.Measure(new Size(100, 100));
-                target.Arrange(new Rect(target.DesiredSize));
-
-                Assert.Equal(55, vp.PixelOffset);
-                Assert.Equal(2, vp.PixelOverflow);
-                Assert.True(vp.IsFull);
-            }
-
-            [Fact]
-            public void Passes_Navigation_Request_To_ILogicalScrollable_Parent()
-            {
-                var target = new VirtualizingStackPanel();
-                var presenter = new TestPresenter { Child = target };
-                var from = new Canvas();
-
-                ((INavigableContainer)target).GetControl(NavigationDirection.Next, from, false);
-
-                Assert.Equal(1, presenter.NavigationRequests.Count);
-                Assert.Equal((NavigationDirection.Next, from), presenter.NavigationRequests[0]);
-            }
-
-            private class TestPresenter : Decorator, ILogicalScrollable
-            {
-                public bool CanHorizontallyScroll { get; set; }
-                public bool CanVerticallyScroll { get; set; }
-                public bool IsLogicalScrollEnabled => true;
-                public Size ScrollSize { get; }
-                public Size PageScrollSize { get; }
-                public Size Extent { get; }
-                public Vector Offset { get; set; }
-                public Size Viewport { get; }
-
-                public event EventHandler ScrollInvalidated;
-
-                public List<(NavigationDirection, Control)> NavigationRequests { get; } = new();
-
-                public bool BringIntoView(Control target, Rect targetRect)
-                {
-                    throw new NotImplementedException();
-                }
-
-                public Control GetControlInDirection(NavigationDirection direction, Control from)
-                {
-                    NavigationRequests.Add((direction, from));
-                    return null;
-                }
-
-                public void RaiseScrollInvalidated(EventArgs e)
-                {
-                    throw new NotImplementedException();
-                }
-            }
-        }
-    }
-}
+////using System;
+////using System.Collections.Generic;
+////using Avalonia.Controls.Primitives;
+////using Avalonia.Input;
+////using Avalonia.LogicalTree;
+////using Moq;
+////using Xunit;
+
+////namespace Avalonia.Controls.UnitTests
+////{
+////    public class VirtualizingStackPanelTests
+////    {
+////        public class Vertical
+////        {
+////            [Fact]
+////            public void Measure_Invokes_Controller_UpdateControls()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var controller = new Mock<IVirtualizingController>();
+
+////                ((IVirtualizingPanel)target).Controller = controller.Object;
+////                target.Measure(new Size(100, 100));
+
+////                controller.Verify(x => x.UpdateControls(), Times.Once());
+////            }
+
+////            [Fact]
+////            public void Measure_Invokes_Controller_UpdateControls_If_AvailableSize_Changes()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var controller = new Mock<IVirtualizingController>();
+
+////                ((IVirtualizingPanel)target).Controller = controller.Object;
+////                target.Measure(new Size(100, 100));
+////                target.InvalidateMeasure();
+////                target.Measure(new Size(100, 100));
+////                target.InvalidateMeasure();
+////                target.Measure(new Size(100, 101));
+
+////                controller.Verify(x => x.UpdateControls(), Times.Exactly(2));
+////            }
+
+////            [Fact]
+////            public void Measure_Does_Not_Invoke_Controller_UpdateControls_If_AvailableSize_Is_The_Same()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var controller = new Mock<IVirtualizingController>();
+
+////                ((IVirtualizingPanel)target).Controller = controller.Object;
+////                target.Measure(new Size(100, 100));
+////                target.InvalidateMeasure();
+////                target.Measure(new Size(100, 100));
+
+////                controller.Verify(x => x.UpdateControls(), Times.Once());
+////            }
+
+////            [Fact]
+////            public void Measure_Invokes_Controller_UpdateControls_If_AvailableSize_Is_The_Same_After_ForceInvalidateMeasure()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var controller = new Mock<IVirtualizingController>();
+
+////                ((IVirtualizingPanel)target).Controller = controller.Object;
+////                target.Measure(new Size(100, 100));
+////                ((IVirtualizingPanel)target).ForceInvalidateMeasure();
+////                target.Measure(new Size(100, 100));
+
+////                controller.Verify(x => x.UpdateControls(), Times.Exactly(2));
+////            }
+
+////            [Fact]
+////            public void Arrange_Invokes_Controller_UpdateControls()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var controller = new Mock<IVirtualizingController>();
+
+////                ((IVirtualizingPanel)target).Controller = controller.Object;
+////                target.Measure(new Size(100, 100));
+////                target.Arrange(new Rect(0, 0, 110, 110));
+
+////                controller.Verify(x => x.UpdateControls(), Times.Exactly(2));
+////            }
+
+////            [Fact]
+////            public void Reports_IsFull_False_Until_Measure_Height_Is_Reached()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var vp = (IVirtualizingPanel)target;
+
+////                target.Measure(new Size(100, 100));
+
+////                Assert.Equal(new Size(0, 0), target.DesiredSize);
+////                Assert.Equal(new Size(0, 0), target.Bounds.Size);
+
+////                Assert.False(vp.IsFull);
+////                Assert.Equal(0, vp.OverflowCount);
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                Assert.False(vp.IsFull);
+////                Assert.Equal(0, vp.OverflowCount);
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                Assert.True(vp.IsFull);
+////                Assert.Equal(0, vp.OverflowCount);
+////            }
+
+////            [Fact]
+////            public void Reports_Overflow_After_Arrange()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var vp = (IVirtualizingPanel)target;
+
+////                target.Measure(new Size(100, 100));
+////                target.Arrange(new Rect(target.DesiredSize));
+
+////                Assert.Equal(new Size(0, 0), target.Bounds.Size);
+
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                Assert.Equal(0, vp.OverflowCount);
+
+////                target.Measure(new Size(100, 100));
+////                target.Arrange(new Rect(target.DesiredSize));
+
+////                Assert.Equal(2, vp.OverflowCount);
+////            }
+
+////            [Fact]
+////            public void Reports_Correct_Overflow_During_Arrange()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var vp = (IVirtualizingPanel)target;
+////                var controller = new Mock<IVirtualizingController>();
+////                var called = false;
+
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                target.Children.Add(new Canvas { Width = 50, Height = 52 });
+////                target.Measure(new Size(100, 100));
+
+////                controller.Setup(x => x.UpdateControls()).Callback(() =>
+////                {
+////                    Assert.Equal(2, vp.PixelOverflow);
+////                    Assert.Equal(0, vp.OverflowCount);
+////                    called = true;
+////                });
+
+////                vp.Controller = controller.Object;
+////                target.Arrange(new Rect(target.DesiredSize));
+
+////                Assert.True(called);
+////            }
+
+////            [Fact]
+////            public void Reports_PixelOverflow_After_Arrange()
+////            {
+////                var target = new VirtualizingStackPanel();
+
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                target.Children.Add(new Canvas { Width = 50, Height = 52 });
+
+////                target.Measure(new Size(100, 100));
+////                target.Arrange(new Rect(target.DesiredSize));
+
+////                Assert.Equal(2, ((IVirtualizingPanel)target).PixelOverflow);
+////            }
+
+////            [Fact]
+////            public void Reports_PixelOverflow_After_Arrange_Smaller_Than_Measure()
+////            {
+////                var target = new VirtualizingStackPanel();
+
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                target.Children.Add(new Canvas { Width = 50, Height = 52 });
+
+////                target.Measure(new Size(100, 100));
+////                target.Arrange(new Rect(0, 0, 50, 50));
+
+////                Assert.Equal(52, ((IVirtualizingPanel)target).PixelOverflow);
+////            }
+
+////            [Fact]
+////            public void Reports_PixelOverflow_With_PixelOffset()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var vp = (IVirtualizingPanel)target;
+
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                target.Children.Add(new Canvas { Width = 50, Height = 52 });
+////                vp.PixelOffset = 2;
+
+////                target.Measure(new Size(100, 100));
+////                target.Arrange(new Rect(target.DesiredSize));
+
+////                Assert.Equal(2, vp.PixelOverflow);
+////            }
+
+////            [Fact]
+////            public void PixelOffset_Can_Be_More_Than_Child_Without_Affecting_IsFull()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var vp = (IVirtualizingPanel)target;
+
+////                target.Children.Add(new Canvas { Width = 50, Height = 50 });
+////                target.Children.Add(new Canvas { Width = 50, Height = 52 });
+////                vp.PixelOffset = 55;
+
+////                target.Measure(new Size(100, 100));
+////                target.Arrange(new Rect(target.DesiredSize));
+
+////                Assert.Equal(55, vp.PixelOffset);
+////                Assert.Equal(2, vp.PixelOverflow);
+////                Assert.True(vp.IsFull);
+////            }
+
+////            [Fact]
+////            public void Passes_Navigation_Request_To_ILogicalScrollable_Parent()
+////            {
+////                var target = new VirtualizingStackPanel();
+////                var presenter = new TestPresenter { Child = target };
+////                var from = new Canvas();
+
+////                ((INavigableContainer)target).GetControl(NavigationDirection.Next, from, false);
+
+////                Assert.Equal(1, presenter.NavigationRequests.Count);
+////                Assert.Equal((NavigationDirection.Next, from), presenter.NavigationRequests[0]);
+////            }
+
+////            private class TestPresenter : Decorator, ILogicalScrollable
+////            {
+////                public bool CanHorizontallyScroll { get; set; }
+////                public bool CanVerticallyScroll { get; set; }
+////                public bool IsLogicalScrollEnabled => true;
+////                public Size ScrollSize { get; }
+////                public Size PageScrollSize { get; }
+////                public Size Extent { get; }
+////                public Vector Offset { get; set; }
+////                public Size Viewport { get; }
+
+////                public event EventHandler ScrollInvalidated;
+
+////                public List<(NavigationDirection, Control)> NavigationRequests { get; } = new();
+
+////                public bool BringIntoView(Control target, Rect targetRect)
+////                {
+////                    throw new NotImplementedException();
+////                }
+
+////                public Control GetControlInDirection(NavigationDirection direction, Control from)
+////                {
+////                    NavigationRequests.Add((direction, from));
+////                    return null;
+////                }
+
+////                public void RaiseScrollInvalidated(EventArgs e)
+////                {
+////                    throw new NotImplementedException();
+////                }
+////            }
+////        }
+////    }
+////}

+ 0 - 1
tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs

@@ -139,7 +139,6 @@ namespace Avalonia.ReactiveUI.UnitTests
                 Child = new ItemsPresenter
                 {
                     Name = "PART_ItemsPresenter",
-                    [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
                 }.RegisterInNameScope(scope)
             });
         }

+ 0 - 1
tests/Avalonia.UnitTests/TestExtensions.cs

@@ -9,6 +9,5 @@ namespace Avalonia.UnitTests
     public static class TestExtensions
     {
         public static void ApplyTemplate(this IContentPresenter presenter) => ((Layoutable)presenter).ApplyTemplate();
-        public static void ApplyTemplate(this IItemsPresenter presenter) => ((Layoutable)presenter).ApplyTemplate();
     }
 }