Skip to content

Commit

Permalink
fix(VirtualizingPanel): Adjust for nullability constraints
Browse files Browse the repository at this point in the history
Fixes incorrect parent panel when removed from the visual tree
  • Loading branch information
jeromelaban committed Feb 16, 2023
1 parent 4318fde commit ac0858d
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,58 @@ public async Task When_Collection_Reset()
}
}

[TestMethod]
public async Task When_Binding_Change()
{
var SUT = new ComboBox();
try
{
WindowHelper.WindowContent = SUT;

var c = new ObservableCollection<string>();
c.Add("One");
c.Add("Two");
c.Add("Three");
c.Add("Four");
c.Add("Five");
c.Add("Six");
c.Add("2-One");
c.Add("2-Two");
c.Add("2-Three");
c.Add("2-Four");
c.Add("2-Five");
c.Add("2-Six");

SUT.SetBinding(ComboBox.ItemsSourceProperty, new Windows.UI.Xaml.Data.Binding() { Path = new("MySource") });
SUT.SetBinding(ComboBox.SelectedItemProperty, new Windows.UI.Xaml.Data.Binding() { Path = new("SelectedItem"), Mode = Windows.UI.Xaml.Data.BindingMode.TwoWay });

SUT.DataContext = new { MySource = c, SelectedItem = "One" };

await WindowHelper.WaitForIdle();

SUT.IsDropDownOpen = true;

await Task.Delay(100);

WindowHelper.WindowContent = null;

await Task.Delay(100);

SUT.DataContext = null;

await WindowHelper.WaitForIdle();

WindowHelper.WindowContent = SUT;
SUT.DataContext = new { MySource = c, SelectedItem = "Two" };

Assert.AreEqual(SUT.Items.Count, 12);
}
finally
{
SUT.IsDropDownOpen = false;
}
}

#if HAS_UNO
[TestMethod]
#if __MACOS__
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#if !NET461
#nullable enable

#if !NET461
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -54,7 +56,7 @@ internal class VirtualizingPanelGenerator
/// </summary>
private readonly Dictionary<int, FrameworkElement> _scrapCache = new Dictionary<int, FrameworkElement>();

private ItemsControl ItemsControl => _owner.ItemsControl;
private ItemsControl? ItemsControl => _owner.ItemsControl;

public VirtualizingPanelGenerator(_VirtualizingPanelLayout owner)
{
Expand Down Expand Up @@ -89,7 +91,7 @@ private void PurgeCache()
/// <summary>
/// Returns a container view bound to the item at <paramref name="index"/>, recycling an available view if possible, or creating a new container if not.
/// </summary>
public FrameworkElement DequeueViewForItem(int index)
public FrameworkElement? DequeueViewForItem(int index)
{
//Try scrap first to save rebinding view
var scrapped = TryGetScrappedContainer(index);
Expand All @@ -115,7 +117,7 @@ public FrameworkElement DequeueViewForItem(int index)
{
this.Log().Debug($"DequeueViewForItem: Creating for index:{index}");
}
container = ItemsControl.GetContainerForIndex(index) as FrameworkElement;
container = ItemsControl?.GetContainerForIndex(index) as FrameworkElement;
}
else
{
Expand All @@ -125,15 +127,15 @@ public FrameworkElement DequeueViewForItem(int index)
}
}

ItemsControl.PrepareContainerForIndex(container, index);
ItemsControl?.PrepareContainerForIndex(container, index);

return container;
}

/// <summary>
/// Try to retrieve a cached container for a given template <paramref name="id"/>. Returns null if none is available.
/// </summary>
private FrameworkElement TryDequeueCachedContainer(int id)
private FrameworkElement? TryDequeueCachedContainer(int id)
{
if (id == IsOwnContainerItemId)
{
Expand All @@ -157,7 +159,7 @@ private FrameworkElement TryDequeueCachedContainer(int id)
/// <summary>
/// Try to retrieve a temporarily-scrapped container for given item <paramref name="index"/>. Returns null if none is available.
/// </summary>
private FrameworkElement TryGetScrappedContainer(int index)
private FrameworkElement? TryGetScrappedContainer(int index)
{
if (_scrapCache.TryGetValue(index, out var container))
{
Expand Down Expand Up @@ -194,7 +196,7 @@ public void RecycleViewForItem(FrameworkElement container, int index, bool clear

if (clearContainer)
{
ItemsControl.CleanUpContainer(container);
ItemsControl?.CleanUpContainer(container);
}
}
else
Expand Down Expand Up @@ -225,7 +227,7 @@ private void DiscardContainer(FrameworkElement container)
if (container.Parent is Panel parent)
{
// Clear the container's Content and DataContext
ItemsControl.CleanUpContainer(container);
ItemsControl?.CleanUpContainer(container);

parent.Children.Remove(container);
}
Expand Down Expand Up @@ -324,7 +326,7 @@ private int GetItemId(int index)
return id;
}

private string GetMethodTag([CallerMemberName] string caller = null)
private string GetMethodTag([CallerMemberName] string? caller = null)
=> $"{nameof(VirtualizingPanelGenerator)}.{caller}()";

internal void ClearIdCache()
Expand Down

0 comments on commit ac0858d

Please sign in to comment.