diff --git a/samples/BindingTest/MainWindow.paml b/samples/BindingTest/MainWindow.paml
index 3a378fcd24..903d1f1050 100644
--- a/samples/BindingTest/MainWindow.paml
+++ b/samples/BindingTest/MainWindow.paml
@@ -6,7 +6,7 @@
-
+
@@ -30,6 +30,11 @@
+
+
+
+
diff --git a/src/Markup/Perspex.Markup.Xaml/Context/NameScopeWrapper.cs b/src/Markup/Perspex.Markup.Xaml/Context/NameScopeWrapper.cs
new file mode 100644
index 0000000000..4cb67ce912
--- /dev/null
+++ b/src/Markup/Perspex.Markup.Xaml/Context/NameScopeWrapper.cs
@@ -0,0 +1,30 @@
+// 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.
+
+namespace Perspex.Markup.Xaml.Context
+{
+ internal class NameScopeWrapper : OmniXaml.INameScope
+ {
+ private Perspex.INameScope _inner;
+
+ public NameScopeWrapper(Perspex.INameScope inner)
+ {
+ _inner = inner;
+ }
+
+ public object Find(string name)
+ {
+ return _inner.Find(name);
+ }
+
+ public void Register(string name, object scopedElement)
+ {
+ _inner.Register(name, scopedElement);
+ }
+
+ public void Unregister(string name)
+ {
+ _inner.Unregister(name);
+ }
+ }
+}
diff --git a/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs b/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs
index 30f2b5ca7c..89203022a9 100644
--- a/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs
@@ -2,8 +2,6 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using Glass;
@@ -11,21 +9,17 @@ using OmniXaml;
using OmniXaml.Builder;
using OmniXaml.TypeConversion;
using OmniXaml.Typing;
+using Perspex.Collections;
using Perspex.Controls;
+using Perspex.Controls.Primitives;
+using Perspex.Controls.Templates;
using Perspex.Input;
-using Perspex.Markup.Xaml.Templates;
using Perspex.Markup.Xaml.Converters;
-using Perspex.Markup.Xaml.Data;
-using Perspex.Markup.Xaml.MarkupExtensions;
using Perspex.Media;
using Perspex.Media.Imaging;
using Perspex.Metadata;
using Perspex.Platform;
using Perspex.Styling;
-using Perspex.Controls.Primitives;
-using Perspex.Controls.Templates;
-using System.Collections;
-using Perspex.Collections;
namespace Perspex.Markup.Xaml.Context
{
@@ -48,9 +42,10 @@ namespace Perspex.Markup.Xaml.Context
var xamlNamespaceRegistry = CreateXamlNamespaceRegistry();
var typeRepository = new PerspexTypeRepository(xamlNamespaceRegistry, typeFactory, featureProvider);
- typeRepository.RegisterMetadata(new Metadata().WithMemberDependency(x => x.Value, x => x.Property));
+ typeRepository.RegisterMetadata(new GenericMetadata().WithRuntimeNameProperty(d => d.Name));
+ typeRepository.RegisterMetadata(new GenericMetadata().WithMemberDependency(x => x.Value, x => x.Property));
typeRepository.RegisterMetadata(
- new Metadata()
+ new GenericMetadata()
.WithMemberDependency(x => x.SelectedIndex, x => x.Items)
.WithMemberDependency(x => x.SelectedItem, x => x.Items));
diff --git a/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlType.cs b/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlType.cs
index 34f0dcca67..c771b30509 100644
--- a/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlType.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlType.cs
@@ -18,6 +18,28 @@ namespace Perspex.Markup.Xaml.Context
{
}
+ public override OmniXaml.INameScope GetNamescope(object instance)
+ {
+ var result = this.UnderlyingType as OmniXaml.INameScope;
+
+ if (result == null)
+ {
+ var visual = instance as Visual;
+
+ if (visual != null)
+ {
+ var perspexNs = (instance as Perspex.INameScope) ?? NameScope.GetNameScope(visual);
+
+ if (perspexNs != null)
+ {
+ result = new NameScopeWrapper(perspexNs);
+ }
+ }
+ }
+
+ return result;
+ }
+
protected override XamlMember LookupMember(string name)
{
return new PerspexXamlMember(name, this, TypeRepository, FeatureProvider);
diff --git a/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs b/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
index 8cc5a981f5..08d7e82387 100644
--- a/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
@@ -4,7 +4,6 @@
using System;
using System.Reactive.Linq;
using System.Reactive.Subjects;
-using OmniXaml.TypeConversion;
using Perspex.Controls;
using Perspex.Markup.Data;
@@ -20,6 +19,11 @@ namespace Perspex.Markup.Xaml.Data
///
public IValueConverter Converter { get; set; }
+ ///
+ /// Gets or sets the name of the element to use as the binding source.
+ ///
+ public string ElementName { get; set; }
+
///
/// Gets or sets the binding mode.
///
@@ -38,7 +42,7 @@ namespace Perspex.Markup.Xaml.Data
///
/// Gets or sets the binding path.
///
- public string SourcePropertyPath { get; set; }
+ public string Path { get; set; }
///
/// Applies the binding to a property on an instance.
@@ -47,8 +51,11 @@ namespace Perspex.Markup.Xaml.Data
/// The target property.
public void Bind(IObservablePropertyBag instance, PerspexProperty property)
{
+ Contract.Requires(instance != null);
+ Contract.Requires(property != null);
+
var subject = CreateSubject(
- instance,
+ instance,
property.PropertyType,
property == Control.DataContextProperty);
@@ -72,15 +79,33 @@ namespace Perspex.Markup.Xaml.Data
Type targetType,
bool targetIsDataContext = false)
{
+ Contract.Requires(target != null);
+ Contract.Requires(targetType != null);
+
+ var pathInfo = ParsePath(Path);
+ ValidateState(pathInfo);
+
ExpressionObserver observer;
- if (RelativeSource == null || RelativeSource.Mode == RelativeSourceMode.DataContext)
+ if (pathInfo.ElementName != null || ElementName != null)
{
- observer = CreateDataContextExpressionSubject(target, targetIsDataContext);
+ observer = CreateElementSubject(
+ (IControl)target,
+ pathInfo.ElementName ?? ElementName,
+ pathInfo.Path);
+ }
+ else if (RelativeSource == null || RelativeSource.Mode == RelativeSourceMode.DataContext)
+ {
+ observer = CreateDataContextSubject(
+ target,
+ pathInfo.Path,
+ targetIsDataContext);
}
else if (RelativeSource.Mode == RelativeSourceMode.TemplatedParent)
{
- observer = CreateTemplatedParentExpressionSubject(target);
+ observer = CreateTemplatedParentSubject(
+ target,
+ pathInfo.Path);
}
else
{
@@ -88,8 +113,8 @@ namespace Perspex.Markup.Xaml.Data
}
return new ExpressionSubject(
- observer,
- targetType,
+ observer,
+ targetType,
Converter ?? DefaultValueConverter.Instance);
}
@@ -101,6 +126,10 @@ namespace Perspex.Markup.Xaml.Data
/// The binding subject.
internal void Bind(IObservablePropertyBag target, PerspexProperty property, ISubject