diff --git a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlObjectWriter.cs b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlObjectWriter.cs index 73cfcfc768..53b3a8585a 100644 --- a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlObjectWriter.cs +++ b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlObjectWriter.cs @@ -18,6 +18,10 @@ namespace Avalonia.Markup.Xaml.PortableXaml return new AvaloniaXamlObjectWriter(schemaContext, writerSettings, nameScope); } + private readonly DelayedValuesHelper _delayedValuesHelper = new DelayedValuesHelper(); + + private AvaloniaNameScope _nameScope; + private AvaloniaXamlObjectWriter( XamlSchemaContext schemaContext, XamlObjectWriterSettings settings, @@ -28,13 +32,32 @@ namespace Avalonia.Markup.Xaml.PortableXaml _nameScope = nameScope; } + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_nameScope != null && Result != null) + { + _nameScope.RegisterOnNameScope(Result); + } + } + + base.Dispose(disposing); + } + protected override void OnAfterBeginInit(object value) { + //not called for avalonia objects + //as it's called inly for + //Portable.Xaml.ComponentModel.ISupportInitialize base.OnAfterBeginInit(value); } protected override void OnAfterEndInit(object value) { + //not called for avalonia objects + //as it's called inly for + //Portable.Xaml.ComponentModel.ISupportInitialize base.OnAfterEndInit(value); } @@ -48,8 +71,6 @@ namespace Avalonia.Markup.Xaml.PortableXaml //Portable.Xaml.ComponentModel.ISupportInitialize //and we have Avalonia.ISupportInitialize so we need some hacks HandleEndEdit(value); - - _objects.Pop(); } protected override void OnBeforeProperties(object value) @@ -57,155 +78,73 @@ namespace Avalonia.Markup.Xaml.PortableXaml //OnAfterBeginInit is not called as it supports only //Portable.Xaml.ComponentModel.ISupportInitialize //and we have Avalonia.ISupportInitialize so we need some hacks - HandleBeginInit(value); _delayedValuesHelper.BeginInit(value); base.OnBeforeProperties(value); - - var target = Current; - - var member = _lastStartMember; - _lastStartMember = null; - - //if (target != null && value != null && member != null && - // member is PropertyXamlMember && !(value is MarkupExtension) && - // member.DeclaringType.ContentProperty?.Name == member.Name && - // !member.IsReadOnly && - // member.Invoker?.UnderlyingSetter != null) - //{ - // //set default content before start properties - // try - // { - // if (!OnSetValue(target, member, value)) - // { - // member.Invoker.SetValue(target, value); - // } - // } - // catch (Exception ex) - // { - // throw new XamlObjectWriterException($"Set value of member '{member}' threw an exception", ex); - // } - //} - - _objects.Push(value); - } - - private AvaloniaNameScope _nameScope; - - private Stack _objects = new Stack(); - - private object Current => _objects.Count > 0 ? _objects.Peek() : null; - - private XamlMember _lastStartMember = null; - - private void HandleBeginInit(object value) - { - (value as Avalonia.ISupportInitialize)?.BeginInit(); - } - - private void HandleEndEdit(object value) - { - (value as Avalonia.ISupportInitialize)?.EndInit(); - } - - private void HandleFinished() - { - if (_nameScope != null && Result != null) - { - _nameScope.RegisterOnNameScope(Result); - } - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - HandleFinished(); - } - - base.Dispose(disposing); - } - - public override void WriteStartMember(XamlMember property) - { - base.WriteStartMember(property); - - _lastStartMember = property; - } - - public override void WriteEndMember() - { - base.WriteEndMember(); - - _lastStartMember = null; } protected override bool OnSetValue(object target, XamlMember member, object value) { - if (value is IBinding) + if (_delayedValuesHelper.TryAdd(target, member, value)) { - //delay bindings - _delayedValuesHelper.Add(new DelayedValue(target, member, value)); return true; } return base.OnSetValue(target, member, value); } - private readonly DelayedValuesHelper _delayedValuesHelper = new DelayedValuesHelper(); - - private class DelayedValue + private void HandleBeginInit(object value) { - public DelayedValue(object target, XamlMember member, object value) - { - Target = target; - Member = member; - Value = value; - } - - public object Target { get; } - - public XamlMember Member { get; } + (value as Avalonia.ISupportInitialize)?.BeginInit(); + } - public object Value { get; } + private void HandleEndEdit(object value) + { + (value as Avalonia.ISupportInitialize)?.EndInit(); } private class DelayedValuesHelper { + private int _cnt; + private HashSet _targets = new HashSet(); private IList _values = new List(); - private int cnt; + private IEnumerable Values => _values; public void BeginInit(object target) { - ++cnt; + ++_cnt; AddTargetIfNeeded(target); } public void EndInit(object target) { - --cnt; + --_cnt; - if (cnt == 0) + if (_cnt == 0) { EndInit(); } } - private void AddTargetIfNeeded(object target) + public bool TryAdd(object target, XamlMember member, object value) { - if (!_targets.Contains(target)) + if (value is IBinding) { - Add(new DelayedValue(target, null, null)); + Add(new DelayedValue(target, member, value)); + + return true; } + + return false; } - public void Add(DelayedValue value) + private void Add(DelayedValue value) { _values.Add(value); @@ -218,6 +157,14 @@ namespace Avalonia.Markup.Xaml.PortableXaml } } + private void AddTargetIfNeeded(object target) + { + if (!_targets.Contains(target)) + { + Add(new DelayedValue(target, null, null)); + } + } + private void EndInit() { //TODO: revisit this @@ -246,7 +193,19 @@ namespace Avalonia.Markup.Xaml.PortableXaml _values.Clear(); } - private IEnumerable Values => _values; + private class DelayedValue + { + public DelayedValue(object target, XamlMember member, object value) + { + Target = target; + Member = member; + Value = value; + } + + public XamlMember Member { get; } + public object Target { get; } + public object Value { get; } + } } } } \ No newline at end of file