Browse Source

Bind DataContext to Parent.DataContext.

Need to special-case binding to DataContext as previously it was trying
to bind to itself. When binding to DataContext, we're binding to the
*parent* DataContext.
pull/242/merge
Steven Kirk 11 years ago
parent
commit
843eb65dea
  1. 41
      src/Markup/Perspex.Markup.Xaml/Binding/XamlBinding.cs
  2. 30
      tests/Perspex.Markup.Xaml.UnitTests/Binding/XamlBindingTests.cs

41
src/Markup/Perspex.Markup.Xaml/Binding/XamlBinding.cs

@ -29,21 +29,42 @@ namespace Perspex.Markup.Xaml.Binding
public void Bind(IObservablePropertyBag instance, PerspexProperty property)
{
if (property == Control.DataContextProperty && instance.InheritanceParent != null)
var subject = new ExpressionSubject(CreateExpressionObserver(instance, property));
if (subject != null)
{
instance = instance.InheritanceParent as IObservablePropertyBag ?? instance;
Bind(instance, property, subject);
}
var subject = new ExpressionSubject(CreateExpressionObserver(instance));
Bind(instance, property, subject);
}
public ExpressionObserver CreateExpressionObserver(IObservablePropertyBag instance)
public ExpressionObserver CreateExpressionObserver(
IObservablePropertyBag instance,
PerspexProperty property)
{
var result = new ExpressionObserver(null, SourcePropertyPath);
var dataContext = instance.GetObservable(Control.DataContextProperty);
dataContext.Subscribe(x => result.Root = x);
return result;
IObservable<object> dataContext = null;
if (property != Control.DataContextProperty)
{
dataContext = instance.GetObservable(Control.DataContextProperty);
}
else
{
var parent = instance.InheritanceParent as IObservablePropertyBag;
if (parent != null)
{
dataContext = parent.GetObservable(Control.DataContextProperty);
}
}
if (dataContext != null)
{
var result = new ExpressionObserver(null, SourcePropertyPath);
dataContext.Subscribe(x => result.Root = x);
return result;
}
return null;
}
internal void Bind(IObservablePropertyBag target, PerspexProperty property, ISubject<object> subject)

30
tests/Perspex.Markup.Xaml.UnitTests/Binding/XamlBindingTests.cs

@ -113,6 +113,36 @@ namespace Perspex.Markup.Xaml.UnitTests.Binding
BindingPriority.LocalValue));
}
[Fact]
public void DataContext_Binding_Should_Use_Parent_DataContext()
{
var parentDataContext = Mock.Of<IHeadered>(x => x.Header == (object)"Foo");
var parent = new Decorator
{
Child = new Control(),
DataContext = parentDataContext,
};
var binding = new XamlBinding
{
SourcePropertyPath = "Header",
};
binding.Bind(parent.Child, Control.DataContextProperty);
Assert.Equal("Foo", parent.Child.DataContext);
parentDataContext = Mock.Of<IHeadered>(x => x.Header == (object)"Bar");
parent.DataContext = parentDataContext;
Assert.Equal("Bar", parent.Child.DataContext);
}
private Mock<IObservablePropertyBag> CreateTarget(object dataContext)
{
return CreateTarget(dataContext: Observable.Never<object>().StartWith(dataContext));
}
private Mock<IObservablePropertyBag> CreateTarget(
IObservable<object> dataContext = null,
IObservable<string> text = null)

Loading…
Cancel
Save