|
|
|
@ -3,9 +3,11 @@ |
|
|
|
|
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Reflection; |
|
|
|
using System.Runtime.CompilerServices; |
|
|
|
using Avalonia.Controls; |
|
|
|
using Avalonia.Data; |
|
|
|
using Avalonia.Logging; |
|
|
|
|
|
|
|
namespace Avalonia.Markup.Xaml.Data |
|
|
|
{ |
|
|
|
@ -50,7 +52,36 @@ namespace Avalonia.Markup.Xaml.Data |
|
|
|
target.Initialized += ApplyBindings; |
|
|
|
} |
|
|
|
|
|
|
|
bindings.Add(new Entry(binding, property)); |
|
|
|
bindings.Add(new BindingEntry(property, binding)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Adds a delayed binding to a control.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="target">The control.</param>
|
|
|
|
/// <param name="property">The property on the control to bind to.</param>
|
|
|
|
/// <param name="binding">The binding.</param>
|
|
|
|
public static void Add(IControl target, PropertyInfo property, Func<IControl, object> value) |
|
|
|
{ |
|
|
|
if (target.IsInitialized) |
|
|
|
{ |
|
|
|
property.SetValue(target, value(target)); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
List<Entry> bindings; |
|
|
|
|
|
|
|
if (!_entries.TryGetValue(target, out bindings)) |
|
|
|
{ |
|
|
|
bindings = new List<Entry>(); |
|
|
|
_entries.Add(target, bindings); |
|
|
|
|
|
|
|
// TODO: Make this a weak event listener.
|
|
|
|
target.Initialized += ApplyBindings; |
|
|
|
} |
|
|
|
|
|
|
|
bindings.Add(new ClrPropertyValueEntry(property, value)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -60,13 +91,13 @@ namespace Avalonia.Markup.Xaml.Data |
|
|
|
/// <param name="control">The control.</param>
|
|
|
|
public static void ApplyBindings(IControl control) |
|
|
|
{ |
|
|
|
List<Entry> bindings; |
|
|
|
List<Entry> entries; |
|
|
|
|
|
|
|
if (_entries.TryGetValue(control, out bindings)) |
|
|
|
if (_entries.TryGetValue(control, out entries)) |
|
|
|
{ |
|
|
|
foreach (var binding in bindings) |
|
|
|
foreach (var entry in entries) |
|
|
|
{ |
|
|
|
control.Bind(binding.Property, binding.Binding); |
|
|
|
entry.Apply(control); |
|
|
|
} |
|
|
|
|
|
|
|
_entries.Remove(control); |
|
|
|
@ -80,9 +111,14 @@ namespace Avalonia.Markup.Xaml.Data |
|
|
|
target.Initialized -= ApplyBindings; |
|
|
|
} |
|
|
|
|
|
|
|
private class Entry |
|
|
|
private abstract class Entry |
|
|
|
{ |
|
|
|
public abstract void Apply(IControl control); |
|
|
|
} |
|
|
|
|
|
|
|
private class BindingEntry : Entry |
|
|
|
{ |
|
|
|
public Entry(IBinding binding, AvaloniaProperty property) |
|
|
|
public BindingEntry(AvaloniaProperty property, IBinding binding) |
|
|
|
{ |
|
|
|
Binding = binding; |
|
|
|
Property = property; |
|
|
|
@ -90,6 +126,41 @@ namespace Avalonia.Markup.Xaml.Data |
|
|
|
|
|
|
|
public IBinding Binding { get; } |
|
|
|
public AvaloniaProperty Property { get; } |
|
|
|
|
|
|
|
public override void Apply(IControl control) |
|
|
|
{ |
|
|
|
control.Bind(Property, Binding); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private class ClrPropertyValueEntry : Entry |
|
|
|
{ |
|
|
|
public ClrPropertyValueEntry(PropertyInfo property, Func<IControl, object> value) |
|
|
|
{ |
|
|
|
Property = property; |
|
|
|
Value = value; |
|
|
|
} |
|
|
|
|
|
|
|
public PropertyInfo Property { get; } |
|
|
|
public Func<IControl, object> Value { get; } |
|
|
|
|
|
|
|
public override void Apply(IControl control) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
Property.SetValue(control, Value(control)); |
|
|
|
} |
|
|
|
catch (Exception e) |
|
|
|
{ |
|
|
|
Logger.Error( |
|
|
|
LogArea.Property, |
|
|
|
control, |
|
|
|
"Error setting {Property} on {Target}: {Exception}", |
|
|
|
Property.Name, |
|
|
|
control, |
|
|
|
e); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|