87 changed files with 916 additions and 929 deletions
@ -1,35 +0,0 @@ |
|||
// 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 System; |
|||
using System.Reactive.Subjects; |
|||
|
|||
namespace Perspex.Markup.Xaml.Data |
|||
{ |
|||
/// <summary>
|
|||
/// Defines a binding that can be created in XAML markup.
|
|||
/// </summary>
|
|||
public interface IXamlBinding |
|||
{ |
|||
/// <summary>
|
|||
/// Applies the binding to a property on an instance.
|
|||
/// </summary>
|
|||
/// <param name="instance">The target instance.</param>
|
|||
/// <param name="property">The target property.</param>
|
|||
void Bind(IObservablePropertyBag instance, PerspexProperty property); |
|||
|
|||
/// <summary>
|
|||
/// Creates a subject that can be used to get and set the value of the binding.
|
|||
/// </summary>
|
|||
/// <param name="target">The target instance.</param>
|
|||
/// <param name="targetType">The type of the target property.</param>
|
|||
/// <param name="targetIsDataContext">
|
|||
/// Whether the target property is the DataContext property.
|
|||
/// </param>
|
|||
/// <returns>An <see cref="ISubject{object}"/>.</returns>
|
|||
ISubject<object> CreateSubject( |
|||
IObservablePropertyBag target, |
|||
Type targetType, |
|||
bool targetIsDataContext = false); |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
// 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 System; |
|||
|
|||
namespace Perspex.Data |
|||
{ |
|||
/// <summary>
|
|||
/// Signifies that a binding can be assigned to a property.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Usually in markup, when a binding is set for a property that property will be bound.
|
|||
/// Applying this attribute to a property indicates that the binding should be assigned to
|
|||
/// the property rather than bound.
|
|||
/// </remarks>
|
|||
[AttributeUsage(AttributeTargets.Property)] |
|||
public sealed class AssignBindingAttribute : Attribute |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
// 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.Data |
|||
{ |
|||
/// <summary>
|
|||
/// Defines possible binding modes.
|
|||
/// </summary>
|
|||
public enum BindingMode |
|||
{ |
|||
/// <summary>
|
|||
/// Uses the default binding mode specified for the property.
|
|||
/// </summary>
|
|||
Default, |
|||
|
|||
/// <summary>
|
|||
/// Binds one way from source to target.
|
|||
/// </summary>
|
|||
OneWay, |
|||
|
|||
/// <summary>
|
|||
/// Binds two-way with the initial value coming from the target.
|
|||
/// </summary>
|
|||
TwoWay, |
|||
|
|||
/// <summary>
|
|||
/// Updates the target when the application starts or when the data context changes.
|
|||
/// </summary>
|
|||
OneTime, |
|||
|
|||
/// <summary>
|
|||
/// Binds one way from target to source.
|
|||
/// </summary>
|
|||
OneWayToSource, |
|||
} |
|||
} |
|||
@ -1,7 +1,7 @@ |
|||
// 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 |
|||
namespace Perspex.Data |
|||
{ |
|||
/// <summary>
|
|||
/// The priority of a binding.
|
|||
@ -0,0 +1,33 @@ |
|||
// 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 System.Reactive.Subjects; |
|||
|
|||
namespace Perspex.Data |
|||
{ |
|||
/// <summary>
|
|||
/// Holds a binding that can be applied to a property on an object.
|
|||
/// </summary>
|
|||
public interface IBinding |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the binding mode.
|
|||
/// </summary>
|
|||
BindingMode Mode { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the binding priority.
|
|||
/// </summary>
|
|||
BindingPriority Priority { get; } |
|||
|
|||
/// <summary>
|
|||
/// Creates a subject that can be used to get and set the value of the binding.
|
|||
/// </summary>
|
|||
/// <param name="target">The target instance.</param>
|
|||
/// <param name="targetProperty">The target property. May be null.</param>
|
|||
/// <returns>An <see cref="ISubject{Object}"/>.</returns>
|
|||
ISubject<object> CreateSubject( |
|||
IPerspexObject target, |
|||
PerspexProperty targetProperty); |
|||
} |
|||
} |
|||
@ -1,95 +0,0 @@ |
|||
// 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 System; |
|||
using System.Reactive.Subjects; |
|||
|
|||
namespace Perspex |
|||
{ |
|||
/// <summary>
|
|||
/// Interface for getting/setting <see cref="PerspexProperty"/> bindings on an object.
|
|||
/// </summary>
|
|||
public interface IObservablePropertyBag : IPropertyBag |
|||
{ |
|||
/// <summary>
|
|||
/// Binds a <see cref="PerspexProperty"/> to an observable.
|
|||
/// </summary>
|
|||
/// <param name="property">The property.</param>
|
|||
/// <param name="source">The observable.</param>
|
|||
/// <param name="priority">The priority of the binding.</param>
|
|||
/// <returns>
|
|||
/// A disposable which can be used to terminate the binding.
|
|||
/// </returns>
|
|||
IDisposable Bind( |
|||
PerspexProperty property, |
|||
IObservable<object> source, |
|||
BindingPriority priority = BindingPriority.LocalValue); |
|||
|
|||
/// <summary>
|
|||
/// Binds a <see cref="PerspexProperty"/> to an observable.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of the property.</typeparam>
|
|||
/// <param name="property">The property.</param>
|
|||
/// <param name="source">The observable.</param>
|
|||
/// <param name="priority">The priority of the binding.</param>
|
|||
/// <returns>
|
|||
/// A disposable which can be used to terminate the binding.
|
|||
/// </returns>
|
|||
IDisposable Bind<T>( |
|||
PerspexProperty<T> property, |
|||
IObservable<T> source, |
|||
BindingPriority priority = BindingPriority.LocalValue); |
|||
|
|||
/// <summary>
|
|||
/// Initiates a two-way binding between <see cref="PerspexProperty"/>s.
|
|||
/// </summary>
|
|||
/// <param name="property">The property on this object.</param>
|
|||
/// <param name="source">The source object.</param>
|
|||
/// <param name="sourceProperty">The property on the source object.</param>
|
|||
/// <param name="priority">The priority of the binding.</param>
|
|||
/// <returns>
|
|||
/// A disposable which can be used to terminate the binding.
|
|||
/// </returns>
|
|||
/// <remarks>
|
|||
/// The binding is first carried out from <paramref name="source"/> to this.
|
|||
/// </remarks>
|
|||
IDisposable BindTwoWay( |
|||
PerspexProperty property, |
|||
PerspexObject source, |
|||
PerspexProperty sourceProperty, |
|||
BindingPriority priority = BindingPriority.LocalValue); |
|||
|
|||
/// <summary>
|
|||
/// Initiates a two-way binding between a <see cref="PerspexProperty"/> and an
|
|||
/// <see cref="ISubject{Object}"/>.
|
|||
/// </summary>
|
|||
/// <param name="property">The property on this object.</param>
|
|||
/// <param name="source">The subject to bind to.</param>
|
|||
/// <param name="priority">The priority of the binding.</param>
|
|||
/// <returns>
|
|||
/// A disposable which can be used to terminate the binding.
|
|||
/// </returns>
|
|||
/// <remarks>
|
|||
/// The binding is first carried out from <paramref name="source"/> to this.
|
|||
/// </remarks>
|
|||
IDisposable BindTwoWay( |
|||
PerspexProperty property, |
|||
ISubject<object> source, |
|||
BindingPriority priority = BindingPriority.LocalValue); |
|||
|
|||
/// <summary>
|
|||
/// Gets an observable for a <see cref="PerspexProperty"/>.
|
|||
/// </summary>
|
|||
/// <param name="property">The property.</param>
|
|||
/// <returns>An observable.</returns>
|
|||
IObservable<object> GetObservable(PerspexProperty property); |
|||
|
|||
/// <summary>
|
|||
/// Gets an observable for a <see cref="PerspexProperty"/>.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of the property.</typeparam>
|
|||
/// <param name="property">The property.</param>
|
|||
/// <returns>An observable.</returns>
|
|||
IObservable<T> GetObservable<T>(PerspexProperty<T> property); |
|||
} |
|||
} |
|||
@ -1,65 +0,0 @@ |
|||
// 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 System; |
|||
|
|||
namespace Perspex.Styling |
|||
{ |
|||
/// <summary>
|
|||
/// A setter for a <see cref="Style"/> whose source is an observable.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// A <see cref="Setter"/> is used to set a <see cref="PerspexProperty"/> value on a
|
|||
/// <see cref="PerspexObject"/> depending on a condition.
|
|||
/// </remarks>
|
|||
public class ObservableSetter : ISetter |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ObservableSetter"/> class.
|
|||
/// </summary>
|
|||
/// <param name="property">The property to set.</param>
|
|||
/// <param name="source">An observable which produces the value for the property.</param>
|
|||
public ObservableSetter(PerspexProperty property, IObservable<object> source) |
|||
{ |
|||
Property = property; |
|||
Source = source; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the property to set.
|
|||
/// </summary>
|
|||
public PerspexProperty Property |
|||
{ |
|||
get; |
|||
set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets an observable which produces the value for the property.
|
|||
/// </summary>
|
|||
public IObservable<object> Source |
|||
{ |
|||
get; |
|||
set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Applies the setter to the control.
|
|||
/// </summary>
|
|||
/// <param name="style">The style that is being applied.</param>
|
|||
/// <param name="control">The control.</param>
|
|||
/// <param name="activator">An optional activator.</param>
|
|||
public void Apply(IStyle style, IStyleable control, IObservable<bool> activator) |
|||
{ |
|||
if (activator == null) |
|||
{ |
|||
control.Bind(Property, Source, BindingPriority.Style); |
|||
} |
|||
else |
|||
{ |
|||
var binding = new StyleBinding(activator, Source, style.ToString()); |
|||
control.Bind(Property, binding, BindingPriority.StyleTrigger); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
// 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 System; |
|||
using System.Collections.Generic; |
|||
using System.Reactive.Linq; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Base.UnitTests |
|||
{ |
|||
public class PerspexObjectTests_GetSubject |
|||
{ |
|||
[Fact] |
|||
public void GetSubject_Returns_Values() |
|||
{ |
|||
var source = new Class1 { Foo = "foo" }; |
|||
var target = source.GetSubject(Class1.FooProperty); |
|||
var result = new List<string>(); |
|||
|
|||
target.Subscribe(x => result.Add(x)); |
|||
source.Foo = "bar"; |
|||
source.Foo = "baz"; |
|||
|
|||
Assert.Equal(new[] { "foo", "bar", "baz" }, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetSubject_Sets_Values() |
|||
{ |
|||
var source = new Class1 { Foo = "foo" }; |
|||
var target = source.GetSubject(Class1.FooProperty); |
|||
|
|||
target.OnNext("bar"); |
|||
Assert.Equal("bar", source.Foo); |
|||
} |
|||
|
|||
private class Class1 : PerspexObject |
|||
{ |
|||
public static readonly PerspexProperty<string> FooProperty = |
|||
PerspexProperty.Register<Class1, string>("Foo", "foodefault"); |
|||
|
|||
public string Foo |
|||
{ |
|||
get { return GetValue(FooProperty); } |
|||
set { SetValue(FooProperty, value); } |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
// 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 System.Linq; |
|||
using Moq; |
|||
using Perspex.Markup.Xaml.Data; |
|||
using Perspex.Platform; |
|||
using Perspex.Styling; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Markup.Xaml.UnitTests |
|||
{ |
|||
public class StyleTests |
|||
{ |
|||
[Fact] |
|||
public void Binding_Should_Be_Assigned_To_Setter_Value_Instead_Of_Bound() |
|||
{ |
|||
using (PerspexLocator.EnterScope()) |
|||
{ |
|||
PerspexLocator.CurrentMutable |
|||
.Bind<IPclPlatformWrapper>() |
|||
.ToConstant(Mock.Of<IPclPlatformWrapper>()); |
|||
|
|||
var xaml = "<Style xmlns='https://github.com/perspex'><Setter Value='{Binding}'/></Style>"; |
|||
var loader = new PerspexXamlLoader(); |
|||
var style = (Style)loader.Load(xaml); |
|||
var setter = (Setter)(style.Setters.First()); |
|||
|
|||
Assert.IsType<Binding>(setter.Value); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
// 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 System.Linq; |
|||
using Moq; |
|||
using Perspex.Controls.Templates; |
|||
using Perspex.Markup.Xaml.Data; |
|||
using Perspex.Markup.Xaml.Templates; |
|||
using Perspex.Platform; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Markup.Xaml.UnitTests |
|||
{ |
|||
public class TreeDataTemplateTests |
|||
{ |
|||
[Fact] |
|||
public void Binding_Should_Be_Assigned_To_ItemsSource_Instead_Of_Bound() |
|||
{ |
|||
using (PerspexLocator.EnterScope()) |
|||
{ |
|||
PerspexLocator.CurrentMutable |
|||
.Bind<IPclPlatformWrapper>() |
|||
.ToConstant(Mock.Of<IPclPlatformWrapper>()); |
|||
|
|||
var xaml = "<DataTemplates xmlns='https://github.com/perspex'><TreeDataTemplate ItemsSource='{Binding}'/></DataTemplates>"; |
|||
var loader = new PerspexXamlLoader(); |
|||
var templates = (DataTemplates)loader.Load(xaml); |
|||
var template = (TreeDataTemplate)(templates.First()); |
|||
|
|||
Assert.IsType<Binding>(template.ItemsSource); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
// 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 System.Reactive.Subjects; |
|||
using Moq; |
|||
using Perspex.Controls; |
|||
using Perspex.Data; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Styling.UnitTests |
|||
{ |
|||
public class SetterTests |
|||
{ |
|||
[Fact] |
|||
public void Setter_Should_Apply_Binding_To_Property() |
|||
{ |
|||
var control = new TextBlock(); |
|||
var subject = new BehaviorSubject<object>("foo"); |
|||
var binding = Mock.Of<IBinding>(x => x.CreateSubject(control, TextBlock.TextProperty) == subject); |
|||
var style = Mock.Of<IStyle>(); |
|||
var setter = new Setter(TextBlock.TextProperty, binding); |
|||
|
|||
setter.Apply(style, control, null); |
|||
|
|||
Assert.Equal("foo", control.Text); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue