Browse Source

Added GetPropertyChangedObservable.

Replaced `GetObservableWithHistory` with `GetPropertyChangedObservable`.
pull/1690/head
Steven Kirk 8 years ago
committed by Steven Kirk
parent
commit
3150d3f10a
  1. 18
      src/Avalonia.Base/AvaloniaObjectExtensions.cs
  2. 46
      src/Avalonia.Base/Reactive/AvaloniaPropertyChangedObservable.cs
  3. 3
      src/Avalonia.Base/Reactive/AvaloniaPropertyObservable.cs
  4. 40
      src/Avalonia.Controls/Mixins/ContentControlMixin.cs

18
src/Avalonia.Base/AvaloniaObjectExtensions.cs

@ -69,26 +69,24 @@ namespace Avalonia
}
/// <summary>
/// Gets an observable for a <see cref="AvaloniaProperty"/>.
/// Gets an observable that listens for property changed events for an
/// <see cref="AvaloniaProperty"/>.
/// </summary>
/// <param name="o">The object.</param>
/// <typeparam name="T">The type of the property.</typeparam>
/// <param name="property">The property.</param>
/// <returns>
/// An observable which when subscribed pushes the old and new values of the property each
/// time it is changed. Note that the observable returned from this method does not fire
/// with the current value of the property immediately.
/// An observable which when subscribed pushes the property changed event args
/// each time a <see cref="IAvaloniaObject.PropertyChanged"/> event is raised
/// for the specified property.
/// </returns>
public static IObservable<Tuple<T, T>> GetObservableWithHistory<T>(
public static IObservable<AvaloniaPropertyChangedEventArgs> GetPropertyChangedObservable(
this IAvaloniaObject o,
AvaloniaProperty<T> property)
AvaloniaProperty property)
{
Contract.Requires<ArgumentNullException>(o != null);
Contract.Requires<ArgumentNullException>(property != null);
return new AvaloniaPropertyObservable<T>(o, property)
.Buffer(2, 1)
.Select(x => Tuple.Create(x[0], x[1]));
return new AvaloniaPropertyChangedObservable(o, property);
}
/// <summary>

46
src/Avalonia.Base/Reactive/AvaloniaPropertyChangedObservable.cs

@ -0,0 +1,46 @@
using System;
namespace Avalonia.Reactive
{
internal class AvaloniaPropertyChangedObservable :
LightweightObservableBase<AvaloniaPropertyChangedEventArgs>,
IDescription
{
private readonly WeakReference<IAvaloniaObject> _target;
private readonly AvaloniaProperty _property;
public AvaloniaPropertyChangedObservable(
IAvaloniaObject target,
AvaloniaProperty property)
{
_target = new WeakReference<IAvaloniaObject>(target);
_property = property;
}
public string Description => $"{_target.GetType().Name}.{_property.Name}";
protected override void Initialize()
{
if (_target.TryGetTarget(out var target))
{
target.PropertyChanged += PropertyChanged;
}
}
protected override void Deinitialize()
{
if (_target.TryGetTarget(out var target))
{
target.PropertyChanged -= PropertyChanged;
}
}
private void PropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == _property)
{
PublishNext(e);
}
}
}
}

3
src/Avalonia.Base/Reactive/AvaloniaPropertyObservable.cs

@ -1,9 +1,8 @@
using System;
using Avalonia.Utilities;
namespace Avalonia.Reactive
{
public class AvaloniaPropertyObservable<T> : LightweightObservableBase<T>, IDescription
internal class AvaloniaPropertyObservable<T> : LightweightObservableBase<T>, IDescription
{
private readonly WeakReference<IAvaloniaObject> _target;
private readonly AvaloniaProperty _property;

40
src/Avalonia.Controls/Mixins/ContentControlMixin.cs

@ -49,11 +49,9 @@ namespace Avalonia.Controls.Mixins
Contract.Requires<ArgumentNullException>(content != null);
Contract.Requires<ArgumentNullException>(logicalChildrenSelector != null);
EventHandler<RoutedEventArgs> templateApplied = (s, ev) =>
void TemplateApplied(object s, RoutedEventArgs ev)
{
var sender = s as TControl;
if (sender != null)
if (s is TControl sender)
{
var e = (TemplateAppliedEventArgs)ev;
var presenter = (IControl)e.NameScope.Find(presenterName);
@ -64,12 +62,12 @@ namespace Avalonia.Controls.Mixins
var logicalChildren = logicalChildrenSelector(sender);
var subscription = presenter
.GetObservableWithHistory(ContentPresenter.ChildProperty)
.Subscribe(child => UpdateLogicalChild(
.GetPropertyChangedObservable(ContentPresenter.ChildProperty)
.Subscribe(c => UpdateLogicalChild(
sender,
logicalChildren,
child.Item1,
child.Item2));
logicalChildren,
c.OldValue,
c.NewValue));
UpdateLogicalChild(
sender,
@ -80,18 +78,16 @@ namespace Avalonia.Controls.Mixins
subscriptions.Value.Add(sender, subscription);
}
}
};
}
TemplatedControl.TemplateAppliedEvent.AddClassHandler(
typeof(TControl),
templateApplied,
TemplateApplied,
RoutingStrategies.Direct);
content.Changed.Subscribe(e =>
{
var sender = e.Sender as TControl;
if (sender != null)
if (e.Sender is TControl sender)
{
var logicalChildren = logicalChildrenSelector(sender);
UpdateLogicalChild(sender, logicalChildren, e.OldValue, e.NewValue);
@ -100,9 +96,7 @@ namespace Avalonia.Controls.Mixins
Control.TemplatedParentProperty.Changed.Subscribe(e =>
{
var sender = e.Sender as TControl;
if (sender != null)
if (e.Sender is TControl sender)
{
var logicalChild = logicalChildrenSelector(sender).FirstOrDefault() as IControl;
logicalChild?.SetValue(Control.TemplatedParentProperty, sender.TemplatedParent);
@ -111,13 +105,9 @@ namespace Avalonia.Controls.Mixins
TemplatedControl.TemplateProperty.Changed.Subscribe(e =>
{
var sender = e.Sender as TControl;
if (sender != null)
if (e.Sender is TControl sender)
{
IDisposable subscription;
if (subscriptions.Value.TryGetValue(sender, out subscription))
if (subscriptions.Value.TryGetValue(sender, out IDisposable subscription))
{
subscription.Dispose();
subscriptions.Value.Remove(sender);
@ -134,9 +124,7 @@ namespace Avalonia.Controls.Mixins
{
if (oldValue != newValue)
{
var child = oldValue as IControl;
if (child != null)
if (oldValue is IControl child)
{
logicalChildren.Remove(child);
}

Loading…
Cancel
Save