Browse Source

Added GetWeakObservable().

And use in in bindings.
pull/467/head
Steven Kirk 10 years ago
parent
commit
7b9a6f29c9
  1. 2
      src/Markup/Perspex.Markup/Data/Plugins/PerspexPropertyAccessorPlugin.cs
  2. 17
      src/Perspex.Base/PerspexObjectExtensions.cs
  3. 3
      src/Perspex.Base/PerspexPropertyChangedEventArgs.cs
  4. 2
      src/Perspex.Base/Reactive/PerspexObservable.cs
  5. 85
      src/Perspex.Base/Reactive/WeakPropertyChangedObservable.cs

2
src/Markup/Perspex.Markup/Data/Plugins/PerspexPropertyAccessorPlugin.cs

@ -74,7 +74,7 @@ namespace Perspex.Markup.Data.Plugins
_reference = reference;
_property = property;
_subscription = Instance.GetObservable(property).Skip(1).Subscribe(changed);
_subscription = Instance.GetWeakObservable(property).Skip(1).Subscribe(changed);
}
public PerspexObject Instance

17
src/Perspex.Base/PerspexObjectExtensions.cs

@ -164,6 +164,23 @@ namespace Perspex
return result;
}
/// <summary>
/// Gets a weak observable for a <see cref="PerspexProperty"/>.
/// </summary>
/// <param name="o">The object.</param>
/// <param name="property">The property.</param>
/// <returns>An observable.</returns>
public static IObservable<object> GetWeakObservable(this IPerspexObject o, PerspexProperty property)
{
Contract.Requires<ArgumentNullException>(o != null);
Contract.Requires<ArgumentNullException>(property != null);
return new WeakPropertyChangedObservable(
new WeakReference<IPerspexObject>(o),
property,
GetDescription(o, property));
}
/// <summary>
/// Binds a property on an <see cref="IPerspexObject"/> to an <see cref="IBinding"/>.
/// </summary>

3
src/Perspex.Base/PerspexPropertyChangedEventArgs.cs

@ -1,6 +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.
using System;
using Perspex.Data;
namespace Perspex
@ -8,7 +9,7 @@ namespace Perspex
/// <summary>
/// Provides information for a perspex property change.
/// </summary>
public class PerspexPropertyChangedEventArgs
public class PerspexPropertyChangedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="PerspexPropertyChangedEventArgs"/> class.

2
src/Perspex.Base/Reactive/PerspexObservable.cs

@ -11,7 +11,7 @@ namespace Perspex.Reactive
/// An <see cref="IObservable{T}"/> with an additional description.
/// </summary>
/// <typeparam name="T">The type of the elements in the sequence.</typeparam>
public sealed class PerspexObservable<T> : ObservableBase<T>, IDescription
public class PerspexObservable<T> : ObservableBase<T>, IDescription
{
private readonly Func<IObserver<T>, IDisposable> _subscribe;

85
src/Perspex.Base/Reactive/WeakPropertyChangedObservable.cs

@ -0,0 +1,85 @@
// 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;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using Perspex.Utilities;
namespace Perspex.Reactive
{
internal class WeakPropertyChangedObservable : ObservableBase<object>,
IWeakSubscriber<PerspexPropertyChangedEventArgs>, IDescription
{
private WeakReference<IPerspexObject> _sourceReference;
private readonly PerspexProperty _property;
private readonly Subject<object> _changed = new Subject<object>();
private int _count;
public WeakPropertyChangedObservable(
WeakReference<IPerspexObject> source,
PerspexProperty property,
string description)
{
_sourceReference = source;
_property = property;
Description = description;
}
public string Description { get; }
public void OnEvent(object sender, PerspexPropertyChangedEventArgs e)
{
if (e.Property == _property)
{
_changed.OnNext(e.NewValue);
}
}
protected override IDisposable SubscribeCore(IObserver<object> observer)
{
IPerspexObject instance;
if (_sourceReference.TryGetTarget(out instance))
{
if (_count == 0)
{
WeakSubscriptionManager.Subscribe(
instance,
nameof(instance.PropertyChanged),
this);
}
observer.OnNext(instance.GetValue(_property));
return Observable.Using(() => Disposable.Create(DecrementCount), _ => _changed)
.Subscribe(observer);
}
else
{
_changed.OnCompleted();
observer.OnCompleted();
return Disposable.Empty;
}
}
private void DecrementCount()
{
if (--_count == 0)
{
IPerspexObject instance;
if (_sourceReference.TryGetTarget(out instance))
{
WeakSubscriptionManager.Unsubscribe(
instance,
nameof(instance.PropertyChanged),
this);
}
}
}
}
}
Loading…
Cancel
Save