diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 29d2c62caf..721a0415f4 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -56,13 +56,6 @@ jobs:
xcodeVersion: '10' # Options: 8, 9, default, specifyPath
args: '-derivedDataPath ./'
- - task: CmdLine@2
- displayName: 'Install CastXML'
- inputs:
- script: |
- brew update
- brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/8a004a91a7fcd3f6620d5b01b6541ff0a640ffba/Formula/castxml.rb
-
- task: CmdLine@2
displayName: 'Install Nuke'
inputs:
diff --git a/src/Avalonia.Controls/ColumnDefinitions.cs b/src/Avalonia.Controls/ColumnDefinitions.cs
index ed4f9dbe99..7e355ab357 100644
--- a/src/Avalonia.Controls/ColumnDefinitions.cs
+++ b/src/Avalonia.Controls/ColumnDefinitions.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Specialized;
using System.Linq;
+using System.Text;
using Avalonia.Collections;
namespace Avalonia.Controls
@@ -13,7 +14,7 @@ namespace Avalonia.Controls
///
/// Initializes a new instance of the class.
///
- public ColumnDefinitions() : base ()
+ public ColumnDefinitions()
{
}
@@ -27,6 +28,11 @@ namespace Avalonia.Controls
AddRange(GridLength.ParseLengths(s).Select(x => new ColumnDefinition(x)));
}
+ public override string ToString()
+ {
+ return string.Join(",", this.Select(x => x.Width));
+ }
+
///
/// Parses a string representation of column definitions collection.
///
@@ -34,4 +40,4 @@ namespace Avalonia.Controls
/// The .
public static ColumnDefinitions Parse(string s) => new ColumnDefinitions(s);
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Controls/Primitives/ScrollBar.cs b/src/Avalonia.Controls/Primitives/ScrollBar.cs
index fc82fcc7a7..477d24dc99 100644
--- a/src/Avalonia.Controls/Primitives/ScrollBar.cs
+++ b/src/Avalonia.Controls/Primitives/ScrollBar.cs
@@ -141,7 +141,7 @@ namespace Avalonia.Controls.Primitives
_ => throw new InvalidOperationException("Invalid value for ScrollBar.Visibility.")
};
- SetValue(IsVisibleProperty, isVisible, BindingPriority.Style);
+ SetValue(IsVisibleProperty, isVisible);
}
protected override void OnKeyDown(KeyEventArgs e)
diff --git a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
index 8bc356bdec..40f1b8dbb9 100644
--- a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
+++ b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
@@ -7,10 +7,10 @@ using System;
using System.Collections;
using System.Collections.Specialized;
using Avalonia.Controls.Templates;
-using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Logging;
+using Avalonia.Utilities;
using Avalonia.VisualTree;
namespace Avalonia.Controls
@@ -681,8 +681,15 @@ namespace Avalonia.Controls
if (oldValue != null)
{
oldValue.UninitializeForContext(LayoutContext);
- oldValue.MeasureInvalidated -= InvalidateMeasureForLayout;
- oldValue.ArrangeInvalidated -= InvalidateArrangeForLayout;
+
+ WeakEventHandlerManager.Unsubscribe(
+ oldValue,
+ nameof(AttachedLayout.MeasureInvalidated),
+ InvalidateMeasureForLayout);
+ WeakEventHandlerManager.Unsubscribe(
+ oldValue,
+ nameof(AttachedLayout.ArrangeInvalidated),
+ InvalidateArrangeForLayout);
// Walk through all the elements and make sure they are cleared
foreach (var element in Children)
@@ -699,8 +706,15 @@ namespace Avalonia.Controls
if (newValue != null)
{
newValue.InitializeForContext(LayoutContext);
- newValue.MeasureInvalidated += InvalidateMeasureForLayout;
- newValue.ArrangeInvalidated += InvalidateArrangeForLayout;
+
+ WeakEventHandlerManager.Subscribe(
+ newValue,
+ nameof(AttachedLayout.MeasureInvalidated),
+ InvalidateMeasureForLayout);
+ WeakEventHandlerManager.Subscribe(
+ newValue,
+ nameof(AttachedLayout.ArrangeInvalidated),
+ InvalidateArrangeForLayout);
}
bool isVirtualizingLayout = newValue != null && newValue is VirtualizingLayout;
diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs
index ddbdae7ed9..e23d6f1471 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs
@@ -8,8 +8,8 @@ namespace Avalonia.Diagnostics.ViewModels
internal abstract class PropertyViewModel : ViewModelBase
{
private const BindingFlags PublicStatic = BindingFlags.Public | BindingFlags.Static;
- private static readonly Type[] StringParameter = new[] { typeof(string) };
- private static readonly Type[] StringIFormatProviderParameters = new[] { typeof(string), typeof(IFormatProvider) };
+ private static readonly Type[] StringParameter = { typeof(string) };
+ private static readonly Type[] StringIFormatProviderParameters = { typeof(string), typeof(IFormatProvider) };
public abstract object Key { get; }
public abstract string Name { get; }
@@ -26,35 +26,46 @@ namespace Avalonia.Diagnostics.ViewModels
}
var converter = TypeDescriptor.GetConverter(value);
- return converter?.ConvertToString(value) ?? value.ToString();
+
+ //CollectionConverter does not deliver any important information. It just displays "(Collection)".
+ if (!converter.CanConvertTo(typeof(string)) ||
+ converter.GetType() == typeof(CollectionConverter))
+ {
+ return value.ToString();
+ }
+
+ return converter.ConvertToString(value);
}
- protected static object ConvertFromString(string s, Type targetType)
+ private static object InvokeParse(string s, Type targetType)
{
- var converter = TypeDescriptor.GetConverter(targetType);
-
- if (converter != null && converter.CanConvertFrom(typeof(string)))
+ var method = targetType.GetMethod("Parse", PublicStatic, null, StringIFormatProviderParameters, null);
+
+ if (method != null)
{
- return converter.ConvertFrom(null, CultureInfo.InvariantCulture, s);
+ return method.Invoke(null, new object[] { s, CultureInfo.InvariantCulture });
}
- else
+
+ method = targetType.GetMethod("Parse", PublicStatic, null, StringParameter, null);
+
+ if (method != null)
{
- var method = targetType.GetMethod("Parse", PublicStatic, null, StringIFormatProviderParameters, null);
+ return method.Invoke(null, new object[] { s });
+ }
- if (method != null)
- {
- return method.Invoke(null, new object[] { s, CultureInfo.InvariantCulture });
- }
+ throw new InvalidCastException("Unable to convert value.");
+ }
- method = targetType.GetMethod("Parse", PublicStatic, null, StringParameter, null);
+ protected static object ConvertFromString(string s, Type targetType)
+ {
+ var converter = TypeDescriptor.GetConverter(targetType);
- if (method != null)
- {
- return method.Invoke(null, new object[] { s });
- }
+ if (converter.CanConvertFrom(typeof(string)))
+ {
+ return converter.ConvertFrom(null, CultureInfo.InvariantCulture, s);
}
- throw new InvalidCastException("Unable to convert value.");
+ return InvokeParse(s, targetType);
}
}
}
diff --git a/src/Avalonia.Layout/Layoutable.cs b/src/Avalonia.Layout/Layoutable.cs
index e62e22f8ec..aca2965ea6 100644
--- a/src/Avalonia.Layout/Layoutable.cs
+++ b/src/Avalonia.Layout/Layoutable.cs
@@ -758,8 +758,6 @@ namespace Avalonia.Layout
protected override void OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e)
{
- base.OnDetachedFromVisualTreeCore(e);
-
if (e.Root is ILayoutRoot r)
{
if (_layoutUpdated is object)
@@ -772,6 +770,8 @@ namespace Avalonia.Layout
r.LayoutManager.UnregisterEffectiveViewportListener(this);
}
}
+
+ base.OnDetachedFromVisualTreeCore(e);
}
///
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs
index ddc0cc4e42..4929283874 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.cs
@@ -1007,10 +1007,12 @@ namespace Avalonia.Win32
if (newProperties.IsResizable)
{
style |= WindowStyles.WS_SIZEFRAME;
+ style |= WindowStyles.WS_MAXIMIZEBOX;
}
else
{
style &= ~WindowStyles.WS_SIZEFRAME;
+ style &= ~WindowStyles.WS_MAXIMIZEBOX;
}
SetStyle(style);
diff --git a/tests/Avalonia.LeakTests/ControlTests.cs b/tests/Avalonia.LeakTests/ControlTests.cs
index 0b81276240..0c7b966f29 100644
--- a/tests/Avalonia.LeakTests/ControlTests.cs
+++ b/tests/Avalonia.LeakTests/ControlTests.cs
@@ -552,6 +552,37 @@ namespace Avalonia.LeakTests
}
}
+ [Fact]
+ public void ItemsRepeater_Is_Freed()
+ {
+ using (Start())
+ {
+ Func run = () =>
+ {
+ var window = new Window
+ {
+ Content = new ItemsRepeater(),
+ };
+
+ window.Show();
+
+ window.LayoutManager.ExecuteInitialLayoutPass();
+ Assert.IsType(window.Presenter.Child);
+
+ window.Content = null;
+ window.LayoutManager.ExecuteLayoutPass();
+ Assert.Null(window.Presenter.Child);
+
+ return window;
+ };
+
+ var result = run();
+
+ dotMemory.Check(memory =>
+ Assert.Equal(0, memory.GetObjects(where => where.Type.Is()).ObjectsCount));
+ }
+ }
+
private IDisposable Start()
{
return UnitTestApplication.Start(TestServices.StyledWindow.With(