Browse Source
Described by XamlBindingTest.Should_Not_Write_To_Old_DataContext. Problem still remains with ListBox.SelectedItems however, that's going to require something more.pull/278/head
5 changed files with 133 additions and 55 deletions
@ -1,21 +1,86 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using Moq; |
|||
using System; |
|||
using Perspex.Controls; |
|||
using Perspex.Markup.Xaml.Binding; |
|||
using OmniXaml.TypeConversion; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Xaml.Base.UnitTest |
|||
{ |
|||
public class XamlBindingTest |
|||
{ |
|||
/// <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 SelectedIndex
|
|||
/// binding and so the unselection is sent back to the ViewModel
|
|||
/// </remarks>
|
|||
[Fact] |
|||
public void TestNullDataContext() |
|||
public void Should_Not_Write_To_Old_DataContext() |
|||
{ |
|||
//var t = new Mock<ITypeConverterProvider>();
|
|||
//var sut = new XamlBinding(t.Object);
|
|||
//sut.BindTo(null);
|
|||
var vm = new OldDataContextViewModel(); |
|||
var target = new OldDataContextTest(); |
|||
|
|||
var fooBinding = new XamlBinding |
|||
{ |
|||
SourcePropertyPath = "Foo", |
|||
BindingMode = BindingMode.TwoWay, |
|||
}; |
|||
|
|||
var barBinding = new XamlBinding |
|||
{ |
|||
SourcePropertyPath = "Bar", |
|||
BindingMode = BindingMode.TwoWay, |
|||
}; |
|||
|
|||
// Bind Foo and Bar to the VM.
|
|||
fooBinding.Bind(target, OldDataContextTest.FooProperty); |
|||
barBinding.Bind(target, OldDataContextTest.BarProperty); |
|||
target.DataContext = vm; |
|||
|
|||
// Make sure the control's Foo and Bar properties are read from the VM
|
|||
Assert.Equal(1, target.GetValue(OldDataContextTest.FooProperty)); |
|||
Assert.Equal(2, target.GetValue(OldDataContextTest.BarProperty)); |
|||
|
|||
// Set DataContext to null.
|
|||
target.DataContext = null; |
|||
|
|||
// Foo and Bar are no longer bound so they return 0, their default value.
|
|||
Assert.Equal(0, target.GetValue(OldDataContextTest.FooProperty)); |
|||
Assert.Equal(0, target.GetValue(OldDataContextTest.BarProperty)); |
|||
|
|||
// The problem was here - DataContext is now null, setting Foo to 0. Bar is bound to
|
|||
// Foo so Bar also gets set to 0. However the Bar binding still had a reference to
|
|||
// the VM and so vm.Bar was set to 0 erroneously.
|
|||
Assert.Equal(1, vm.Foo); |
|||
Assert.Equal(2, vm.Bar); |
|||
} |
|||
|
|||
private class OldDataContextViewModel |
|||
{ |
|||
public int Foo { get; set; } = 1; |
|||
public int Bar { get; set; } = 2; |
|||
} |
|||
|
|||
private class OldDataContextTest : Control |
|||
{ |
|||
public static readonly PerspexProperty<int> FooProperty = |
|||
PerspexProperty.Register<OldDataContextTest, int>("Foo"); |
|||
|
|||
public static readonly PerspexProperty<int> BarProperty = |
|||
PerspexProperty.Register<OldDataContextTest, int>("Bar"); |
|||
|
|||
public OldDataContextTest() |
|||
{ |
|||
Bind(BarProperty, GetObservable(FooProperty)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
Loading…
Reference in new issue