Browse Source

Merge branch 'master' into datagrid1

pull/3564/head
Steven Kirk 7 years ago
committed by GitHub
parent
commit
204cee0699
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      src/Avalonia.Base/AvaloniaObject.cs
  2. 4
      src/Avalonia.Base/PropertyStore/BindingEntry.cs
  3. 5
      src/Avalonia.Base/PropertyStore/IValueSink.cs
  4. 5
      src/Avalonia.Base/PropertyStore/PriorityValue.cs
  5. 9
      src/Avalonia.Base/ValueStore.cs
  6. 42
      src/Avalonia.Controls/TextBox.cs
  7. 2
      src/Avalonia.Controls/Window.cs
  8. 2
      src/Avalonia.Input/IInputElement.cs
  9. 11
      src/Avalonia.Native/WindowImplBase.cs
  10. 27
      src/Avalonia.Styling/StyledElement.cs
  11. 4
      src/Avalonia.Styling/Styling/Setter.cs
  12. 35
      src/Avalonia.Styling/Styling/Style.cs
  13. 4
      src/Avalonia.Styling/Styling/Styles.cs
  14. 4
      src/Avalonia.Themes.Default/TextBox.xaml
  15. 26
      src/Avalonia.Visuals/Visual.cs
  16. 105
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs
  17. 1
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs
  18. 12
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_SetValue.cs
  19. 47
      tests/Avalonia.Benchmarks/Styling/StyleAttachBenchmark.cs
  20. 51
      tests/Avalonia.Controls.UnitTests/WindowTests.cs
  21. 52
      tests/Avalonia.LeakTests/ControlTests.cs

8
src/Avalonia.Base/AvaloniaObject.cs

@ -478,7 +478,13 @@ namespace Avalonia
}
}
void IValueSink.Completed(AvaloniaProperty property, IPriorityValueEntry entry) { }
void IValueSink.Completed<T>(
StyledPropertyBase<T> property,
IPriorityValueEntry entry,
Optional<T> oldValue)
{
((IValueSink)this).ValueChanged(property, BindingPriority.Unset, oldValue, default);
}
/// <summary>
/// Called for each inherited property when the <see cref="InheritanceParent"/> changes.

4
src/Avalonia.Base/PropertyStore/BindingEntry.cs

@ -48,10 +48,10 @@ namespace Avalonia.PropertyStore
{
_subscription?.Dispose();
_subscription = null;
_sink.Completed(Property, this);
_sink.Completed(Property, this, Value);
}
public void OnCompleted() => _sink.Completed(Property, this);
public void OnCompleted() => _sink.Completed(Property, this, Value);
public void OnError(Exception error)
{

5
src/Avalonia.Base/PropertyStore/IValueSink.cs

@ -15,6 +15,9 @@ namespace Avalonia.PropertyStore
Optional<T> oldValue,
BindingValue<T> newValue);
void Completed(AvaloniaProperty property, IPriorityValueEntry entry);
void Completed<T>(
StyledPropertyBase<T> property,
IPriorityValueEntry entry,
Optional<T> oldValue);
}
}

5
src/Avalonia.Base/PropertyStore/PriorityValue.cs

@ -117,7 +117,10 @@ namespace Avalonia.PropertyStore
UpdateEffectiveValue();
}
void IValueSink.Completed(AvaloniaProperty property, IPriorityValueEntry entry)
void IValueSink.Completed<TValue>(
StyledPropertyBase<TValue> property,
IPriorityValueEntry entry,
Optional<TValue> oldValue)
{
_entries.Remove((IPriorityValueEntry<T>)entry);
UpdateEffectiveValue();

9
src/Avalonia.Base/ValueStore.cs

@ -148,7 +148,7 @@ namespace Avalonia
_values.Remove(property);
_sink.ValueChanged(
property,
BindingPriority.LocalValue,
BindingPriority.Unset,
old,
BindingValue<T>.Unset);
}
@ -190,13 +190,17 @@ namespace Avalonia
_sink.ValueChanged(property, priority, oldValue, newValue);
}
void IValueSink.Completed(AvaloniaProperty property, IPriorityValueEntry entry)
void IValueSink.Completed<T>(
StyledPropertyBase<T> property,
IPriorityValueEntry entry,
Optional<T> oldValue)
{
if (_values.TryGetValue(property, out var slot))
{
if (slot == entry)
{
_values.Remove(property);
_sink.Completed(property, entry, oldValue);
}
}
}
@ -228,6 +232,7 @@ namespace Avalonia
else
{
var priorityValue = new PriorityValue<T>(_owner, property, this, l);
priorityValue.SetValue(value, priority);
_values.SetValue(property, priorityValue);
}
}

42
src/Avalonia.Controls/TextBox.cs

@ -14,6 +14,7 @@ using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Metadata;
using Avalonia.Data;
using Avalonia.Layout;
using Avalonia.Utilities;
namespace Avalonia.Controls
@ -72,6 +73,18 @@ namespace Avalonia.Controls
public static readonly StyledProperty<TextAlignment> TextAlignmentProperty =
TextBlock.TextAlignmentProperty.AddOwner<TextBox>();
/// <summary>
/// Defines the <see cref="HorizontalAlignment"/> property.
/// </summary>
public static readonly StyledProperty<HorizontalAlignment> HorizontalContentAlignmentProperty =
ContentControl.HorizontalContentAlignmentProperty.AddOwner<TextBox>();
/// <summary>
/// Defines the <see cref="VerticalAlignment"/> property.
/// </summary>
public static readonly StyledProperty<VerticalAlignment> VerticalContentAlignmentProperty =
ContentControl.VerticalContentAlignmentProperty.AddOwner<TextBox>();
public static readonly StyledProperty<TextWrapping> TextWrappingProperty =
TextBlock.TextWrappingProperty.AddOwner<TextBox>();
@ -262,6 +275,24 @@ namespace Avalonia.Controls
}
}
/// <summary>
/// Gets or sets the horizontal alignment of the content within the control.
/// </summary>
public HorizontalAlignment HorizontalContentAlignment
{
get { return GetValue(HorizontalContentAlignmentProperty); }
set { SetValue(HorizontalContentAlignmentProperty, value); }
}
/// <summary>
/// Gets or sets the vertical alignment of the content within the control.
/// </summary>
public VerticalAlignment VerticalContentAlignment
{
get { return GetValue(VerticalContentAlignmentProperty); }
set { SetValue(VerticalContentAlignmentProperty, value); }
}
public TextAlignment TextAlignment
{
get { return GetValue(TextAlignmentProperty); }
@ -316,8 +347,7 @@ namespace Avalonia.Controls
!AcceptsReturn &&
Text?.Length > 0)
{
SelectionStart = 0;
SelectionEnd = Text.Length;
SelectAll();
}
else
{
@ -673,8 +703,7 @@ namespace Avalonia.Controls
SelectionEnd = StringUtils.NextWord(text, index);
break;
case 3:
SelectionStart = 0;
SelectionEnd = text.Length;
SelectAll();
break;
}
}
@ -896,7 +925,10 @@ namespace Avalonia.Controls
CaretIndex = caretIndex;
}
private void SelectAll()
/// <summary>
/// Select all text in the TextBox
/// </summary>
public void SelectAll()
{
SelectionStart = 0;
SelectionEnd = Text?.Length ?? 0;

2
src/Avalonia.Controls/Window.cs

@ -529,7 +529,7 @@ namespace Avalonia.Controls
{
var sizeToContent = SizeToContent;
var clientSize = ClientSize;
Size constraint = clientSize;
var constraint = availableSize;
if ((sizeToContent & SizeToContent.Width) != 0)
{

2
src/Avalonia.Input/IInputElement.cs

@ -63,7 +63,7 @@ namespace Avalonia.Input
event EventHandler<PointerReleasedEventArgs> PointerReleased;
/// <summary>
/// Occurs when the mouse wheen is scrolled over the control.
/// Occurs when the mouse wheel is scrolled over the control.
/// </summary>
event EventHandler<PointerWheelEventArgs> PointerWheelChanged;

11
src/Avalonia.Native/WindowImplBase.cs

@ -162,9 +162,12 @@ namespace Avalonia.Native
void IAvnWindowBaseEvents.Resized(AvnSize size)
{
var s = new Size(size.Width, size.Height);
_parent._savedLogicalSize = s;
_parent.Resized?.Invoke(s);
if (_parent._native != null)
{
var s = new Size(size.Width, size.Height);
_parent._savedLogicalSize = s;
_parent.Resized?.Invoke(s);
}
}
void IAvnWindowBaseEvents.PositionChanged(AvnPoint position)
@ -317,7 +320,7 @@ namespace Avalonia.Native
_native.SetTopMost(value);
}
public double Scaling => _native.GetScaling();
public double Scaling => _native?.GetScaling() ?? 1;
public Action Deactivated { get; set; }
public Action Activated { get; set; }

27
src/Avalonia.Styling/StyledElement.cs

@ -573,9 +573,12 @@ namespace Avalonia
element._dataContextUpdating = true;
element.OnDataContextBeginUpdate();
foreach (var child in element.LogicalChildren)
var logicalChildren = element.LogicalChildren;
var logicalChildrenCount = logicalChildren.Count;
for (var i = 0; i < logicalChildrenCount; i++)
{
if (child is StyledElement s &&
if (element.LogicalChildren[i] is StyledElement s &&
s.InheritanceParent == element &&
!s.IsSet(DataContextProperty))
{
@ -646,9 +649,15 @@ namespace Avalonia
AttachedToLogicalTree?.Invoke(this, e);
}
foreach (var child in LogicalChildren.OfType<StyledElement>())
var logicalChildren = LogicalChildren;
var logicalChildrenCount = logicalChildren.Count;
for (var i = 0; i < logicalChildrenCount; i++)
{
child.OnAttachedToLogicalTreeCore(e);
if (logicalChildren[i] is StyledElement child)
{
child.OnAttachedToLogicalTreeCore(e);
}
}
}
@ -661,9 +670,15 @@ namespace Avalonia
OnDetachedFromLogicalTree(e);
DetachedFromLogicalTree?.Invoke(this, e);
foreach (var child in LogicalChildren.OfType<StyledElement>())
var logicalChildren = LogicalChildren;
var logicalChildrenCount = logicalChildren.Count;
for (var i = 0; i < logicalChildrenCount; i++)
{
child.OnDetachedFromLogicalTreeCore(e);
if (logicalChildren[i] is StyledElement child)
{
child.OnDetachedFromLogicalTreeCore(e);
}
}
#if DEBUG

4
src/Avalonia.Styling/Styling/Setter.cs

@ -78,8 +78,6 @@ namespace Avalonia.Styling
{
Contract.Requires<ArgumentNullException>(control != null);
var description = style?.ToString();
if (Property == null)
{
throw new InvalidOperationException("Setter.Property must be set.");
@ -107,6 +105,8 @@ namespace Avalonia.Styling
}
else
{
var description = style?.ToString();
var activated = new ActivatedValue(activator, value, description);
return control.Bind(Property, activated, BindingPriority.StyleTrigger);
}

35
src/Avalonia.Styling/Styling/Style.cs

@ -116,13 +116,21 @@ namespace Avalonia.Styling
if (match.IsMatch)
{
var controlSubscriptions = GetSubscriptions(control);
var subs = new CompositeDisposable(Setters.Count + Animations.Count);
if (control is Animatable animatable)
var animatable = control as Animatable;
var setters = Setters;
var settersCount = setters.Count;
var animations = Animations;
var animationsCount = animations.Count;
var subs = new CompositeDisposable(settersCount + (animatable != null ? animationsCount : 0) + 1);
if (animatable != null)
{
foreach (var animation in Animations)
for (var i = 0; i < animationsCount; i++)
{
var animation = animations[i];
var obsMatch = match.Activator;
if (match.Result == SelectorMatchResult.AlwaysThisType ||
@ -133,17 +141,19 @@ namespace Avalonia.Styling
var sub = animation.Apply(animatable, null, obsMatch);
subs.Add(sub);
}
}
}
foreach (var setter in Setters)
for (var i = 0; i < settersCount; i++)
{
var setter = setters[i];
var sub = setter.Apply(this, control, match.Activator);
subs.Add(sub);
}
subs.Add(Disposable.Create((subs, Subscriptions) , state => state.Subscriptions.Remove(state.subs)));
controlSubscriptions.Add(subs);
controlSubscriptions.Add(Disposable.Create(() => Subscriptions.Remove(subs)));
Subscriptions.Add(subs);
}
@ -151,18 +161,23 @@ namespace Avalonia.Styling
}
else if (control == container)
{
var setters = Setters;
var settersCount = setters.Count;
var controlSubscriptions = GetSubscriptions(control);
var subs = new CompositeDisposable(Setters.Count);
var subs = new CompositeDisposable(settersCount + 1);
foreach (var setter in Setters)
for (var i = 0; i < settersCount; i++)
{
var setter = setters[i];
var sub = setter.Apply(this, control, null);
subs.Add(sub);
}
subs.Add(Disposable.Create((subs, Subscriptions), state => state.Subscriptions.Remove(state.subs)));
controlSubscriptions.Add(subs);
controlSubscriptions.Add(Disposable.Create(() => Subscriptions.Remove(subs)));
Subscriptions.Add(subs);
return true;
}

4
src/Avalonia.Styling/Styling/Styles.cs

@ -239,8 +239,10 @@ namespace Avalonia.Styling
/// <inheritdoc/>
public bool Remove(IStyle item) => _styles.Remove(item);
public AvaloniaList<IStyle>.Enumerator GetEnumerator() => _styles.GetEnumerator();
/// <inheritdoc/>
public IEnumerator<IStyle> GetEnumerator() => _styles.GetEnumerator();
IEnumerator<IStyle> IEnumerable<IStyle>.GetEnumerator() => _styles.GetEnumerator();
/// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator() => _styles.GetEnumerator();

4
src/Avalonia.Themes.Default/TextBox.xaml

@ -12,7 +12,9 @@
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel Margin="{TemplateBinding Padding}">
<DockPanel Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<TextBlock Name="floatingWatermark"
Foreground="{DynamicResource ThemeAccentBrush}"

26
src/Avalonia.Visuals/Visual.cs

@ -386,11 +386,18 @@ namespace Avalonia
AttachedToVisualTree?.Invoke(this, e);
InvalidateVisual();
if (VisualChildren != null)
var visualChildren = VisualChildren;
if (visualChildren != null)
{
foreach (Visual child in VisualChildren.OfType<Visual>())
var visualChildrenCount = visualChildren.Count;
for (var i = 0; i < visualChildrenCount; i++)
{
child.OnAttachedToVisualTreeCore(e);
if (visualChildren[i] is Visual child)
{
child.OnAttachedToVisualTreeCore(e);
}
}
}
}
@ -415,11 +422,18 @@ namespace Avalonia
DetachedFromVisualTree?.Invoke(this, e);
e.Root?.Renderer?.AddDirty(this);
if (VisualChildren != null)
var visualChildren = VisualChildren;
if (visualChildren != null)
{
foreach (Visual child in VisualChildren.OfType<Visual>())
var visualChildrenCount = visualChildren.Count;
for (var i = 0; i < visualChildrenCount; i++)
{
child.OnDetachedFromVisualTreeCore(e);
if (visualChildren[i] is Visual child)
{
child.OnDetachedFromVisualTreeCore(e);
}
}
}
}

105
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs

@ -132,6 +132,111 @@ namespace Avalonia.Base.UnitTests
Assert.Equal("foo", target.GetValue(property));
}
[Fact]
public void Completing_LocalValue_Binding_Raises_PropertyChanged()
{
var target = new Class1();
var source = new BehaviorSubject<BindingValue<string>>("foo");
var property = Class1.FooProperty;
var raised = 0;
target.Bind(property, source);
Assert.Equal("foo", target.GetValue(property));
target.PropertyChanged += (s, e) =>
{
Assert.Equal(BindingPriority.Unset, e.Priority);
Assert.Equal(property, e.Property);
Assert.Equal("foo", e.OldValue as string);
Assert.Equal("foodefault", e.NewValue as string);
++raised;
};
source.OnCompleted();
Assert.Equal("foodefault", target.GetValue(property));
Assert.Equal(1, raised);
}
[Fact]
public void Completing_Style_Binding_Raises_PropertyChanged()
{
var target = new Class1();
var source = new BehaviorSubject<BindingValue<string>>("foo");
var property = Class1.FooProperty;
var raised = 0;
target.Bind(property, source, BindingPriority.Style);
Assert.Equal("foo", target.GetValue(property));
target.PropertyChanged += (s, e) =>
{
Assert.Equal(BindingPriority.Unset, e.Priority);
Assert.Equal(property, e.Property);
Assert.Equal("foo", e.OldValue as string);
Assert.Equal("foodefault", e.NewValue as string);
++raised;
};
source.OnCompleted();
Assert.Equal("foodefault", target.GetValue(property));
Assert.Equal(1, raised);
}
[Fact]
public void Completing_LocalValue_Binding_With_Style_Binding_Raises_PropertyChanged()
{
var target = new Class1();
var source = new BehaviorSubject<BindingValue<string>>("foo");
var property = Class1.FooProperty;
var raised = 0;
target.Bind(property, new BehaviorSubject<string>("bar"), BindingPriority.Style);
target.Bind(property, source);
Assert.Equal("foo", target.GetValue(property));
target.PropertyChanged += (s, e) =>
{
Assert.Equal(BindingPriority.Style, e.Priority);
Assert.Equal(property, e.Property);
Assert.Equal("foo", e.OldValue as string);
Assert.Equal("bar", e.NewValue as string);
++raised;
};
source.OnCompleted();
Assert.Equal("bar", target.GetValue(property));
Assert.Equal(1, raised);
}
[Fact]
public void Disposing_LocalValue_Binding_Raises_PropertyChanged()
{
var target = new Class1();
var source = new BehaviorSubject<BindingValue<string>>("foo");
var property = Class1.FooProperty;
var raised = 0;
var sub = target.Bind(property, source);
Assert.Equal("foo", target.GetValue(property));
target.PropertyChanged += (s, e) =>
{
Assert.Equal(BindingPriority.Unset, e.Priority);
Assert.Equal(property, e.Property);
Assert.Equal("foo", e.OldValue as string);
Assert.Equal("foodefault", e.NewValue as string);
++raised;
};
sub.Dispose();
Assert.Equal("foodefault", target.GetValue(property));
Assert.Equal(1, raised);
}
[Fact]
public void Setting_Style_Value_Overrides_Binding_Permanently()
{

1
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Direct.cs

@ -188,6 +188,7 @@ namespace Avalonia.Base.UnitTests
target.PropertyChanged += (s, e) =>
{
Assert.Same(target, s);
Assert.Equal(BindingPriority.LocalValue, e.Priority);
Assert.Equal(Class1.FooProperty, e.Property);
Assert.Equal("newvalue", (string)e.OldValue);
Assert.Equal("unset", (string)e.NewValue);

12
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_SetValue.cs

@ -30,6 +30,7 @@ namespace Avalonia.Base.UnitTests
target.PropertyChanged += (s, e) =>
{
Assert.Same(target, s);
Assert.Equal(BindingPriority.Unset, e.Priority);
Assert.Equal(Class1.FooProperty, e.Property);
Assert.Equal("newvalue", (string)e.OldValue);
Assert.Equal("foodefault", (string)e.NewValue);
@ -239,6 +240,17 @@ namespace Avalonia.Base.UnitTests
Assert.Equal("two", target.GetValue(Class1.FooProperty));
}
[Fact]
public void SetValue_Animation_Overrides_LocalValue()
{
Class1 target = new Class1();
target.SetValue(Class1.FooProperty, "one", BindingPriority.LocalValue);
Assert.Equal("one", target.GetValue(Class1.FooProperty));
target.SetValue(Class1.FooProperty, "two", BindingPriority.Animation);
Assert.Equal("two", target.GetValue(Class1.FooProperty));
}
[Fact]
public void Setting_UnsetValue_Reverts_To_Default_Value()
{

47
tests/Avalonia.Benchmarks/Styling/StyleAttachBenchmark.cs

@ -0,0 +1,47 @@
using System;
using System.Runtime.CompilerServices;
using Avalonia.Controls;
using Avalonia.UnitTests;
using BenchmarkDotNet.Attributes;
namespace Avalonia.Benchmarks.Styling
{
[MemoryDiagnoser]
public class StyleAttachBenchmark : IDisposable
{
private readonly IDisposable _app;
private readonly TestRoot _root;
private readonly TextBox _control;
public StyleAttachBenchmark()
{
_app = UnitTestApplication.Start(
TestServices.StyledWindow.With(
renderInterface: new NullRenderingPlatform(),
threadingInterface: new NullThreadingPlatform()));
_root = new TestRoot(true, null)
{
Renderer = new NullRenderer(),
};
_control = new TextBox();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public void AttachTextBoxStyles()
{
var styles = UnitTestApplication.Current.Styles;
styles.Attach(_control, UnitTestApplication.Current);
styles.Detach();
}
public void Dispose()
{
_app.Dispose();
}
}
}

51
tests/Avalonia.Controls.UnitTests/WindowTests.cs

@ -341,11 +341,62 @@ namespace Avalonia.Controls.UnitTests
}
}
[Fact]
public void Child_Should_Be_Measured_With_Width_And_Height_If_SizeToContent_Is_Manual()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var child = new ChildControl();
var target = new Window
{
Width = 100,
Height = 50,
SizeToContent = SizeToContent.Manual,
Content = child
};
target.Show();
Assert.Equal(new Size(100, 50), child.MeasureSize);
}
}
[Fact]
public void Child_Should_Be_Measured_With_Infinity_If_SizeToContent_Is_WidthAndHeight()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var child = new ChildControl();
var target = new Window
{
Width = 100,
Height = 50,
SizeToContent = SizeToContent.WidthAndHeight,
Content = child
};
target.Show();
Assert.Equal(Size.Infinity, child.MeasureSize);
}
}
private IWindowImpl CreateImpl(Mock<IRenderer> renderer)
{
return Mock.Of<IWindowImpl>(x =>
x.Scaling == 1 &&
x.CreateRenderer(It.IsAny<IRenderRoot>()) == renderer.Object);
}
private class ChildControl : Control
{
public Size MeasureSize { get; private set; }
protected override Size MeasureOverride(Size availableSize)
{
MeasureSize = availableSize;
return base.MeasureOverride(availableSize);
}
}
}
}

52
tests/Avalonia.LeakTests/ControlTests.cs

@ -8,8 +8,10 @@ using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Diagnostics;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.UnitTests;
using Avalonia.VisualTree;
using JetBrains.dotMemoryUnit;
@ -370,6 +372,56 @@ namespace Avalonia.LeakTests
}
}
[Fact]
public void Control_With_Style_RenderTransform_Is_Freed()
{
// # Issue #3545
using (Start())
{
Func<Window> run = () =>
{
var window = new Window
{
Styles =
{
new Style(x => x.OfType<Canvas>())
{
Setters =
{
new Setter
{
Property = Visual.RenderTransformProperty,
Value = new RotateTransform(45),
}
}
}
},
Content = new Canvas()
};
window.Show();
// Do a layout and make sure that Canvas gets added to visual tree with
// its render transform.
window.LayoutManager.ExecuteInitialLayoutPass(window);
var canvas = Assert.IsType<Canvas>(window.Presenter.Child);
Assert.IsType<RotateTransform>(canvas.RenderTransform);
// Clear the content and ensure the Canvas is removed.
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<Canvas>()).ObjectsCount));
}
}
private IDisposable Start()
{
return UnitTestApplication.Start(TestServices.StyledWindow);

Loading…
Cancel
Save