|
|
@@ -9,7 +9,6 @@ using System.Reflection;
|
|
|
using Avalonia.Data;
|
|
|
using Avalonia.Logging;
|
|
|
using Avalonia.Utilities;
|
|
|
-using System.Collections;
|
|
|
|
|
|
namespace Avalonia.Markup.Data.Plugins
|
|
|
{
|
|
|
@@ -19,43 +18,29 @@ namespace Avalonia.Markup.Data.Plugins
|
|
|
/// </summary>
|
|
|
public class InpcPropertyAccessorPlugin : IPropertyAccessorPlugin
|
|
|
{
|
|
|
- /// <summary>
|
|
|
- /// Checks whether this plugin can handle accessing the properties of the specified object.
|
|
|
- /// </summary>
|
|
|
- /// <param name="reference">The object.</param>
|
|
|
- /// <returns>True if the plugin can handle the object; otherwise false.</returns>
|
|
|
- public bool Match(WeakReference reference)
|
|
|
- {
|
|
|
- Contract.Requires<ArgumentNullException>(reference != null);
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public bool Match(WeakReference reference) => true;
|
|
|
|
|
|
/// <summary>
|
|
|
/// Starts monitoring the value of a property on an object.
|
|
|
/// </summary>
|
|
|
/// <param name="reference">The object.</param>
|
|
|
/// <param name="propertyName">The property name.</param>
|
|
|
- /// <param name="changed">A function to call when the property changes.</param>
|
|
|
/// <returns>
|
|
|
/// An <see cref="IPropertyAccessor"/> interface through which future interactions with the
|
|
|
/// property will be made.
|
|
|
/// </returns>
|
|
|
- public IPropertyAccessor Start(
|
|
|
- WeakReference reference,
|
|
|
- string propertyName,
|
|
|
- Action<object> changed)
|
|
|
+ public IPropertyAccessor Start(WeakReference reference, string propertyName)
|
|
|
{
|
|
|
Contract.Requires<ArgumentNullException>(reference != null);
|
|
|
Contract.Requires<ArgumentNullException>(propertyName != null);
|
|
|
- Contract.Requires<ArgumentNullException>(changed != null);
|
|
|
|
|
|
var instance = reference.Target;
|
|
|
var p = instance.GetType().GetRuntimeProperties().FirstOrDefault(_ => _.Name == propertyName);
|
|
|
|
|
|
if (p != null)
|
|
|
{
|
|
|
- return new Accessor(reference, p, changed);
|
|
|
+ return new Accessor(reference, p);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -65,78 +50,99 @@ namespace Avalonia.Markup.Data.Plugins
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private class Accessor : IPropertyAccessor, IWeakSubscriber<PropertyChangedEventArgs>
|
|
|
+ private class Accessor : PropertyAccessorBase, IWeakSubscriber<PropertyChangedEventArgs>
|
|
|
{
|
|
|
private readonly WeakReference _reference;
|
|
|
private readonly PropertyInfo _property;
|
|
|
- private readonly Action<object> _changed;
|
|
|
|
|
|
- public Accessor(
|
|
|
- WeakReference reference,
|
|
|
- PropertyInfo property,
|
|
|
- Action<object> changed)
|
|
|
+ public Accessor(WeakReference reference, PropertyInfo property)
|
|
|
{
|
|
|
Contract.Requires<ArgumentNullException>(reference != null);
|
|
|
Contract.Requires<ArgumentNullException>(property != null);
|
|
|
|
|
|
_reference = reference;
|
|
|
_property = property;
|
|
|
- _changed = changed;
|
|
|
+ }
|
|
|
|
|
|
- var inpc = reference.Target as INotifyPropertyChanged;
|
|
|
+ public override Type PropertyType => _property.PropertyType;
|
|
|
|
|
|
- if (inpc != null)
|
|
|
+ public override object Value
|
|
|
+ {
|
|
|
+ get
|
|
|
{
|
|
|
- WeakSubscriptionManager.Subscribe<PropertyChangedEventArgs>(
|
|
|
- inpc,
|
|
|
- nameof(inpc.PropertyChanged),
|
|
|
- this);
|
|
|
+ var o = _reference.Target;
|
|
|
+ return (o != null) ? _property.GetValue(o) : null;
|
|
|
}
|
|
|
- else
|
|
|
+ }
|
|
|
+
|
|
|
+ public override bool SetValue(object value, BindingPriority priority)
|
|
|
+ {
|
|
|
+ if (_property.CanWrite)
|
|
|
{
|
|
|
- Logger.Warning(
|
|
|
- LogArea.Binding,
|
|
|
- this,
|
|
|
- "Bound to property {Property} on {Source} which does not implement INotifyPropertyChanged",
|
|
|
- property.Name,
|
|
|
- reference.Target,
|
|
|
- reference.Target.GetType());
|
|
|
+ _property.SetValue(_reference.Target, value);
|
|
|
+ return true;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- public Type PropertyType => _property.PropertyType;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- public object Value => _property.GetValue(_reference.Target);
|
|
|
+ void IWeakSubscriber<PropertyChangedEventArgs>.OnEvent(object sender, PropertyChangedEventArgs e)
|
|
|
+ {
|
|
|
+ if (e.PropertyName == _property.Name || string.IsNullOrEmpty(e.PropertyName))
|
|
|
+ {
|
|
|
+ SendCurrentValue();
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- public void Dispose()
|
|
|
+ protected override void Dispose(bool disposing)
|
|
|
{
|
|
|
var inpc = _reference.Target as INotifyPropertyChanged;
|
|
|
|
|
|
if (inpc != null)
|
|
|
{
|
|
|
- WeakSubscriptionManager.Unsubscribe<PropertyChangedEventArgs>(
|
|
|
+ WeakSubscriptionManager.Unsubscribe(
|
|
|
inpc,
|
|
|
nameof(inpc.PropertyChanged),
|
|
|
this);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public bool SetValue(object value, BindingPriority priority)
|
|
|
+ protected override void SubscribeCore(IObserver<object> observer)
|
|
|
{
|
|
|
- if (_property.CanWrite)
|
|
|
+ SendCurrentValue();
|
|
|
+ SubscribeToChanges();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void SendCurrentValue()
|
|
|
+ {
|
|
|
+ try
|
|
|
{
|
|
|
- _property.SetValue(_reference.Target, value);
|
|
|
- return true;
|
|
|
+ var value = Value;
|
|
|
+ Observer.OnNext(value);
|
|
|
}
|
|
|
-
|
|
|
- return false;
|
|
|
+ catch { }
|
|
|
}
|
|
|
|
|
|
- void IWeakSubscriber<PropertyChangedEventArgs>.OnEvent(object sender, PropertyChangedEventArgs e)
|
|
|
+ private void SubscribeToChanges()
|
|
|
{
|
|
|
- if (e.PropertyName == _property.Name || string.IsNullOrEmpty(e.PropertyName))
|
|
|
+ var inpc = _reference.Target as INotifyPropertyChanged;
|
|
|
+
|
|
|
+ if (inpc != null)
|
|
|
+ {
|
|
|
+ WeakSubscriptionManager.Subscribe<PropertyChangedEventArgs>(
|
|
|
+ inpc,
|
|
|
+ nameof(inpc.PropertyChanged),
|
|
|
+ this);
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- _changed(Value);
|
|
|
+ Logger.Information(
|
|
|
+ LogArea.Binding,
|
|
|
+ this,
|
|
|
+ "Bound to property {Property} on {Source} which does not implement INotifyPropertyChanged",
|
|
|
+ _property.Name,
|
|
|
+ _reference.Target,
|
|
|
+ _reference.Target.GetType());
|
|
|
}
|
|
|
}
|
|
|
}
|