|
|
@@ -8,6 +8,7 @@ using Perspex.Collections;
|
|
|
using Perspex.Controls.Presenters;
|
|
|
using Perspex.Controls.Primitives;
|
|
|
using Perspex.Controls.Templates;
|
|
|
+using Perspex.Markup.Xaml.Binding;
|
|
|
using Xunit;
|
|
|
|
|
|
namespace Perspex.Controls.UnitTests.Primitives
|
|
|
@@ -354,8 +355,74 @@ namespace Perspex.Controls.UnitTests.Primitives
|
|
|
Assert.Equal(new[] { "baz", "qux", "qiz" }, target.SelectedItems.Cast<object>().ToList());
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Tests a problem discovered with ListBox with selection.
|
|
|
+ /// </summary>
|
|
|
+ /// <remarks>
|
|
|
+ /// - Items is bound to DataContext first, followed by say SelectedIndex
|
|
|
+ /// - When the ListBox is removed from the visual tree, DataContext becomes null (as it's
|
|
|
+ /// inherited)
|
|
|
+ /// - This changes Items to null, which changes SelectedIndex to null as there are no
|
|
|
+ /// longer any items
|
|
|
+ /// - However, the news that DataContext is now null hasn't yet reached the SelectedItems
|
|
|
+ /// binding and so the unselection is sent back to the ViewModel
|
|
|
+ ///
|
|
|
+ /// This is a similar problem to that tested by XamlBindingTest.Should_Not_Write_To_Old_DataContext.
|
|
|
+ /// However, that tests a general property binding problem: here we are writing directly
|
|
|
+ /// to the SelectedItems collection - not via a binding - so it's something that the
|
|
|
+ /// binding system cannot solve. Instead we solve it by not clearing SelectedItems when
|
|
|
+ /// DataContext is in the process of changing.
|
|
|
+ /// </remarks>
|
|
|
+ [Fact]
|
|
|
+ public void Should_Not_Write_To_Old_DataContext()
|
|
|
+ {
|
|
|
+ var vm = new OldDataContextViewModel();
|
|
|
+ var target = new TestSelector();
|
|
|
+
|
|
|
+ var itemsBinding = new XamlBinding
|
|
|
+ {
|
|
|
+ SourcePropertyPath = "Items",
|
|
|
+ BindingMode = BindingMode.OneWay,
|
|
|
+ };
|
|
|
+
|
|
|
+ var selectedItemsBinding = new XamlBinding
|
|
|
+ {
|
|
|
+ SourcePropertyPath = "SelectedItems",
|
|
|
+ BindingMode = BindingMode.OneWay,
|
|
|
+ };
|
|
|
+
|
|
|
+ // Bind Items and SelectedItems to the VM.
|
|
|
+ itemsBinding.Bind(target, TestSelector.ItemsProperty);
|
|
|
+ selectedItemsBinding.Bind(target, TestSelector.SelectedItemsProperty);
|
|
|
+
|
|
|
+ // Set DataContext and SelectedIndex
|
|
|
+ target.DataContext = vm;
|
|
|
+ target.SelectedIndex = 1;
|
|
|
+
|
|
|
+ // Make sure SelectedItems are written back to VM.
|
|
|
+ Assert.Equal(new[] { "bar" }, vm.SelectedItems);
|
|
|
+
|
|
|
+ // Clear DataContext and ensure that SelectedItems is still set in the VM.
|
|
|
+ target.DataContext = null;
|
|
|
+ Assert.Equal(new[] { "bar" }, vm.SelectedItems);
|
|
|
+ }
|
|
|
+
|
|
|
+ private ControlTemplate Template()
|
|
|
+ {
|
|
|
+ return new ControlTemplate<SelectingItemsControl>(control =>
|
|
|
+ new ItemsPresenter
|
|
|
+ {
|
|
|
+ Name = "itemsPresenter",
|
|
|
+ [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
|
|
|
+ [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
private class TestSelector : SelectingItemsControl
|
|
|
{
|
|
|
+ public static readonly new PerspexProperty<IList> SelectedItemsProperty =
|
|
|
+ SelectingItemsControl.SelectedItemsProperty;
|
|
|
+
|
|
|
public new IList SelectedItems
|
|
|
{
|
|
|
get { return base.SelectedItems; }
|
|
|
@@ -374,15 +441,16 @@ namespace Perspex.Controls.UnitTests.Primitives
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private ControlTemplate Template()
|
|
|
+ private class OldDataContextViewModel
|
|
|
{
|
|
|
- return new ControlTemplate<SelectingItemsControl>(control =>
|
|
|
- new ItemsPresenter
|
|
|
- {
|
|
|
- Name = "itemsPresenter",
|
|
|
- [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
|
|
|
- [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
|
|
|
- });
|
|
|
+ public OldDataContextViewModel()
|
|
|
+ {
|
|
|
+ Items = new List<string> { "foo", "bar" };
|
|
|
+ SelectedItems = new List<string>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<string> Items { get; }
|
|
|
+ public List<string> SelectedItems { get; }
|
|
|
}
|
|
|
}
|
|
|
}
|