Browse Source

Manually handle name scope registrations

pull/2705/head
Nikita Tsukanov 7 years ago
parent
commit
fa55755b71
  1. 2
      src/Avalonia.Controls/AutoCompleteBox.cs
  2. 21
      src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
  3. 19
      src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs
  4. 14
      src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
  5. 6
      src/Avalonia.Controls/Presenters/ContentPresenter.cs
  6. 30
      src/Avalonia.Controls/Primitives/TemplatedControl.cs
  7. 4
      src/Avalonia.Controls/Templates/FuncControlTemplate.cs
  8. 6
      src/Avalonia.Controls/Templates/FuncControlTemplate`2.cs
  9. 8
      src/Avalonia.Controls/Templates/FuncDataTemplate.cs
  10. 26
      src/Avalonia.Controls/Templates/FuncDataTemplate`1.cs
  11. 24
      src/Avalonia.Controls/Templates/FuncTemplateNameScopeExtensions.cs
  12. 13
      src/Avalonia.Controls/Templates/FuncTemplate`2.cs
  13. 4
      src/Avalonia.Controls/Templates/FuncTreeDataTemplate.cs
  14. 15
      src/Avalonia.Controls/Templates/FuncTreeDataTemplate`1.cs
  15. 34
      src/Avalonia.Controls/UserControl.cs
  16. 34
      src/Avalonia.Controls/Window.cs
  17. 4
      src/Avalonia.ReactiveUI/AutoDataTemplateBindingHook.cs
  18. 15
      src/Avalonia.Styling/Controls/NameScope.cs
  19. 41
      src/Avalonia.Styling/Controls/NameScopeExtensions.cs
  20. 21
      src/Avalonia.Styling/StyledElement.cs
  21. 1
      src/Avalonia.Styling/Styling/Setter.cs
  22. 1
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs
  23. 69
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AddNameScopeRegistration.cs
  24. 12
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  25. 1
      src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
  26. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github
  27. 8
      src/Markup/Avalonia.Markup.Xaml/XamlTypes.cs
  28. 10
      tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs
  29. 4
      tests/Avalonia.Controls.UnitTests/CarouselTests.cs
  30. 10
      tests/Avalonia.Controls.UnitTests/ComboBoxTests.cs
  31. 12
      tests/Avalonia.Controls.UnitTests/ContentControlTests.cs
  32. 12
      tests/Avalonia.Controls.UnitTests/DatePickerTests.cs
  33. 21
      tests/Avalonia.Controls.UnitTests/GridSplitterTests.cs
  34. 6
      tests/Avalonia.Controls.UnitTests/HeaderedItemsControlTests .cs
  35. 10
      tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs
  36. 30
      tests/Avalonia.Controls.UnitTests/ListBoxTests.cs
  37. 13
      tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs
  38. 17
      tests/Avalonia.Controls.UnitTests/Mixins/ContentControlMixinTests.cs
  39. 18
      tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_InTemplate.cs
  40. 16
      tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Standalone.cs
  41. 4
      tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Unrooted.cs
  42. 2
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs
  43. 2
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs
  44. 8
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs
  45. 6
      tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs
  46. 8
      tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
  47. 6
      tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs
  48. 10
      tests/Avalonia.Controls.UnitTests/Primitives/ScrollBarTests.cs
  49. 4
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs
  50. 4
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs
  51. 10
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs
  52. 4
      tests/Avalonia.Controls.UnitTests/Primitives/TabStripTests.cs
  53. 58
      tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs
  54. 12
      tests/Avalonia.Controls.UnitTests/ScrollViewerTests.cs
  55. 18
      tests/Avalonia.Controls.UnitTests/TabControlTests.cs
  56. 4
      tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
  57. 4
      tests/Avalonia.Controls.UnitTests/TextBoxTests_DataValidation.cs
  58. 4
      tests/Avalonia.Controls.UnitTests/TopLevelTests.cs
  59. 18
      tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
  60. 6
      tests/Avalonia.Controls.UnitTests/UserControlTests.cs
  61. 4
      tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs
  62. 4
      tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs
  63. 10
      tests/Avalonia.Markup.UnitTests/Data/BindingTests_ElementName.cs
  64. 5
      tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests_Converters.cs
  65. 6
      tests/Avalonia.Markup.UnitTests/Data/TemplateBindingTests.cs
  66. 4
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/BindingExtensionTests.cs
  67. 4
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs
  68. 4
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs
  69. 8
      tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs
  70. 8
      tests/Avalonia.ReactiveUI.UnitTests/TransitioningContentControlTest.cs
  71. 82
      tests/Avalonia.Styling.UnitTests/ControlLocatorTests.cs
  72. 12
      tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
  73. 13
      tests/Avalonia.Styling.UnitTests/SetterTests.cs
  74. 15
      tests/Avalonia.Styling.UnitTests/StyledElementTests.cs
  75. 69
      tests/Avalonia.Styling.UnitTests/StyledElementTests_NameScope.cs
  76. 4
      tests/Avalonia.Styling.UnitTests/StyledElementTests_Resources.cs
  77. 48
      tests/Avalonia.UnitTests/TestRoot.cs
  78. 33
      tests/Avalonia.UnitTests/TestTemplatedRoot.cs

2
src/Avalonia.Controls/AutoCompleteBox.cs

@ -795,7 +795,7 @@ namespace Avalonia.Controls
var template = var template =
new FuncDataTemplate( new FuncDataTemplate(
typeof(object), typeof(object),
o => (o, _) =>
{ {
var control = new ContentControl(); var control = new ContentControl();
control.Bind(ContentControl.ContentProperty, value); control.Bind(ContentControl.ContentProperty, value);

21
src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs

@ -8,7 +8,7 @@ using JetBrains.Annotations;
namespace Avalonia.Controls.Embedding namespace Avalonia.Controls.Embedding
{ {
public class EmbeddableControlRoot : TopLevel, IStyleable, IFocusScope, INameScope, IDisposable public class EmbeddableControlRoot : TopLevel, IStyleable, IFocusScope, IDisposable
{ {
public EmbeddableControlRoot(IEmbeddableWindowImpl impl) : base(impl) public EmbeddableControlRoot(IEmbeddableWindowImpl impl) : base(impl)
{ {
@ -51,25 +51,6 @@ namespace Avalonia.Controls.Embedding
return rv; return rv;
} }
private readonly NameScope _nameScope = new NameScope();
public event EventHandler<NameScopeEventArgs> Registered
{
add { _nameScope.Registered += value; }
remove { _nameScope.Registered -= value; }
}
public event EventHandler<NameScopeEventArgs> Unregistered
{
add { _nameScope.Unregistered += value; }
remove { _nameScope.Unregistered -= value; }
}
public void Register(string name, object element) => _nameScope.Register(name, element);
public object Find(string name) => _nameScope.Find(name);
public void Unregister(string name) => _nameScope.Unregister(name);
Type IStyleable.StyleKey => typeof(EmbeddableControlRoot); Type IStyleable.StyleKey => typeof(EmbeddableControlRoot);
public void Dispose() => PlatformImpl?.Dispose(); public void Dispose() => PlatformImpl?.Dispose();
} }

19
src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs

@ -30,25 +30,6 @@ namespace Avalonia.Controls.Embedding.Offscreen
init.EndInit(); init.EndInit();
} }
} }
private readonly NameScope _nameScope = new NameScope();
public event EventHandler<NameScopeEventArgs> Registered
{
add { _nameScope.Registered += value; }
remove { _nameScope.Registered -= value; }
}
public event EventHandler<NameScopeEventArgs> Unregistered
{
add { _nameScope.Unregistered += value; }
remove { _nameScope.Unregistered -= value; }
}
public void Register(string name, object element) => _nameScope.Register(name, element);
public object Find(string name) => _nameScope.Find(name);
public void Unregister(string name) => _nameScope.Unregister(name);
Type IStyleable.StyleKey => typeof(EmbeddableControlRoot); Type IStyleable.StyleKey => typeof(EmbeddableControlRoot);
public void Dispose() public void Dispose()

14
src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs

@ -92,7 +92,6 @@ namespace Avalonia.Controls.Generators
result.DataContext = item; result.DataContext = item;
} }
NameScope.SetNameScope((Control)(object)result, new NameScope());
Index.Add(item, result); Index.Add(item, result);
return result; return result;
@ -123,11 +122,20 @@ namespace Avalonia.Controls.Generators
return false; return false;
} }
class WrapperTreeDataTemplate : ITreeDataTemplate
{
private readonly IDataTemplate _inner;
public WrapperTreeDataTemplate(IDataTemplate inner) => _inner = inner;
public IControl Build(object param) => _inner.Build(param);
public bool SupportsRecycling => _inner.SupportsRecycling;
public bool Match(object data) => _inner.Match(data);
public InstancedBinding ItemsSelector(object item) => null;
}
private ITreeDataTemplate GetTreeDataTemplate(object item, IDataTemplate primary) private ITreeDataTemplate GetTreeDataTemplate(object item, IDataTemplate primary)
{ {
var template = Owner.FindDataTemplate(item, primary) ?? FuncDataTemplate.Default; var template = Owner.FindDataTemplate(item, primary) ?? FuncDataTemplate.Default;
var treeTemplate = template as ITreeDataTemplate ?? var treeTemplate = template as ITreeDataTemplate ?? new WrapperTreeDataTemplate(template);
new FuncTreeDataTemplate(typeof(object), template.Build, x => null);
return treeTemplate; return treeTemplate;
} }
} }

6
src/Avalonia.Controls/Presenters/ContentPresenter.cs

@ -325,12 +325,6 @@ namespace Avalonia.Controls.Presenters
{ {
_dataTemplate = dataTemplate; _dataTemplate = dataTemplate;
newChild = _dataTemplate.Build(content); newChild = _dataTemplate.Build(content);
// Give the new control its own name scope.
if (newChild is Control controlResult)
{
NameScope.SetNameScope(controlResult, new NameScope());
}
} }
} }
else else

30
src/Avalonia.Controls/Primitives/TemplatedControl.cs

@ -258,13 +258,16 @@ namespace Avalonia.Controls.Primitives
Logger.Verbose(LogArea.Control, this, "Creating control template"); Logger.Verbose(LogArea.Control, this, "Creating control template");
var child = template.Build(this); var child = template.Build(this);
var nameScope = new NameScope();
NameScope.SetNameScope((Control)child, nameScope);
ApplyTemplatedParent(child); ApplyTemplatedParent(child);
RegisterNames(child, nameScope);
((ISetLogicalParent)child).SetParent(this); ((ISetLogicalParent)child).SetParent(this);
VisualChildren.Add(child); VisualChildren.Add(child);
var nameScope = (child is StyledElement styledChild) ? NameScope.GetNameScope(styledChild) : null;
// Existing code kinda expect to see a NameScope even if it's empty
if (nameScope == null)
nameScope = new NameScope();
OnTemplateApplied(new TemplateAppliedEventArgs(nameScope)); OnTemplateApplied(new TemplateAppliedEventArgs(nameScope));
} }
@ -342,26 +345,5 @@ namespace Avalonia.Controls.Primitives
} }
} }
} }
/// <summary>
/// Registers each control with its name scope.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="nameScope">The name scope.</param>
private void RegisterNames(IControl control, INameScope nameScope)
{
if (control.Name != null)
{
nameScope.Register(control.Name, control);
}
if (control.TemplatedParent == this)
{
foreach (IControl child in control.GetLogicalChildren())
{
RegisterNames(child, nameScope);
}
}
}
} }
} }

4
src/Avalonia.Controls/Templates/FuncControlTemplate.cs

@ -16,9 +16,9 @@ namespace Avalonia.Controls.Templates
/// Initializes a new instance of the <see cref="FuncControlTemplate"/> class. /// Initializes a new instance of the <see cref="FuncControlTemplate"/> class.
/// </summary> /// </summary>
/// <param name="build">The build function.</param> /// <param name="build">The build function.</param>
public FuncControlTemplate(Func<ITemplatedControl, IControl> build) public FuncControlTemplate(Func<ITemplatedControl, INameScope, IControl> build)
: base(build) : base(build)
{ {
} }
} }
} }

6
src/Avalonia.Controls/Templates/FuncControlTemplate`2.cs

@ -17,9 +17,9 @@ namespace Avalonia.Controls.Templates
/// Initializes a new instance of the <see cref="FuncControlTemplate{T}"/> class. /// Initializes a new instance of the <see cref="FuncControlTemplate{T}"/> class.
/// </summary> /// </summary>
/// <param name="build">The build function.</param> /// <param name="build">The build function.</param>
public FuncControlTemplate(Func<T, IControl> build) public FuncControlTemplate(Func<T, INameScope, IControl> build)
: base(x => build((T)x)) : base((x, s) => build((T)x, s))
{ {
} }
} }
} }

8
src/Avalonia.Controls/Templates/FuncDataTemplate.cs

@ -17,7 +17,7 @@ namespace Avalonia.Controls.Templates
/// </summary> /// </summary>
public static readonly FuncDataTemplate Default = public static readonly FuncDataTemplate Default =
new FuncDataTemplate<object>( new FuncDataTemplate<object>(
data => (data, s) =>
{ {
if (data != null) if (data != null)
{ {
@ -49,7 +49,7 @@ namespace Avalonia.Controls.Templates
/// <param name="supportsRecycling">Whether the control can be recycled.</param> /// <param name="supportsRecycling">Whether the control can be recycled.</param>
public FuncDataTemplate( public FuncDataTemplate(
Type type, Type type,
Func<object, IControl> build, Func<object, INameScope, IControl> build,
bool supportsRecycling = false) bool supportsRecycling = false)
: this(o => IsInstance(o, type), build, supportsRecycling) : this(o => IsInstance(o, type), build, supportsRecycling)
{ {
@ -67,7 +67,7 @@ namespace Avalonia.Controls.Templates
/// <param name="supportsRecycling">Whether the control can be recycled.</param> /// <param name="supportsRecycling">Whether the control can be recycled.</param>
public FuncDataTemplate( public FuncDataTemplate(
Func<object, bool> match, Func<object, bool> match,
Func<object, IControl> build, Func<object, INameScope, IControl> build,
bool supportsRecycling = false) bool supportsRecycling = false)
: base(build) : base(build)
{ {
@ -105,4 +105,4 @@ namespace Avalonia.Controls.Templates
return (o != null) && t.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo()); return (o != null) && t.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo());
} }
} }
} }

26
src/Avalonia.Controls/Templates/FuncDataTemplate`1.cs

@ -18,7 +18,7 @@ namespace Avalonia.Controls.Templates
/// A function which when passed an object of <typeparamref name="T"/> returns a control. /// A function which when passed an object of <typeparamref name="T"/> returns a control.
/// </param> /// </param>
/// <param name="supportsRecycling">Whether the control can be recycled.</param> /// <param name="supportsRecycling">Whether the control can be recycled.</param>
public FuncDataTemplate(Func<T, IControl> build, bool supportsRecycling = false) public FuncDataTemplate(Func<T, INameScope, IControl> build, bool supportsRecycling = false)
: base(typeof(T), CastBuild(build), supportsRecycling) : base(typeof(T), CastBuild(build), supportsRecycling)
{ {
} }
@ -35,12 +35,30 @@ namespace Avalonia.Controls.Templates
/// <param name="supportsRecycling">Whether the control can be recycled.</param> /// <param name="supportsRecycling">Whether the control can be recycled.</param>
public FuncDataTemplate( public FuncDataTemplate(
Func<T, bool> match, Func<T, bool> match,
Func<T, IControl> build, Func<T, INameScope, IControl> build,
bool supportsRecycling = false) bool supportsRecycling = false)
: base(CastMatch(match), CastBuild(build), supportsRecycling) : base(CastMatch(match), CastBuild(build), supportsRecycling)
{ {
} }
/// <summary>
/// Initializes a new instance of the <see cref="FuncDataTemplate{T}"/> class.
/// </summary>
/// <param name="match">
/// A function which determines whether the data template matches the specified data.
/// </param>
/// <param name="build">
/// A function which when passed an object of <typeparamref name="T"/> returns a control.
/// </param>
/// <param name="supportsRecycling">Whether the control can be recycled.</param>
public FuncDataTemplate(
Func<T, bool> match,
Func<T, IControl> build,
bool supportsRecycling = false)
: this(match, (a, _) => build(a), supportsRecycling)
{
}
/// <summary> /// <summary>
/// Casts a strongly typed match function to a weakly typed one. /// Casts a strongly typed match function to a weakly typed one.
/// </summary> /// </summary>
@ -57,9 +75,9 @@ namespace Avalonia.Controls.Templates
/// <typeparam name="TResult">The strong data type.</typeparam> /// <typeparam name="TResult">The strong data type.</typeparam>
/// <param name="f">The strongly typed function.</param> /// <param name="f">The strongly typed function.</param>
/// <returns>The weakly typed function.</returns> /// <returns>The weakly typed function.</returns>
private static Func<object, TResult> CastBuild<TResult>(Func<T, TResult> f) private static Func<object, INameScope, TResult> CastBuild<TResult>(Func<T, INameScope, TResult> f)
{ {
return o => f((T)o); return (o, s) => f((T)o, s);
} }
} }
} }

24
src/Avalonia.Controls/Templates/FuncTemplateNameScopeExtensions.cs

@ -0,0 +1,24 @@
using System;
namespace Avalonia.Controls.Templates
{
public static class FuncTemplateNameScopeExtensions
{
public static T RegisterInNameScope<T>(this T control, INameScope scope)
where T : StyledElement
{
scope.Register(control.Name, control);
return control;
}
public static T WithNameScope<T>(this T control, INameScope scope)
where T : StyledElement
{
var existingScope = NameScope.GetNameScope(control);
if (existingScope != null && existingScope != scope)
throw new InvalidOperationException("Control already has a name scope");
NameScope.SetNameScope(control, scope);
return control;
}
}
}

13
src/Avalonia.Controls/Templates/FuncTemplate`2.cs

@ -13,13 +13,13 @@ namespace Avalonia.Controls.Templates
public class FuncTemplate<TParam, TControl> : ITemplate<TParam, TControl> public class FuncTemplate<TParam, TControl> : ITemplate<TParam, TControl>
where TControl : IControl where TControl : IControl
{ {
private readonly Func<TParam, TControl> _func; private readonly Func<TParam, INameScope, TControl> _func;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="FuncTemplate{TControl, TParam}"/> class. /// Initializes a new instance of the <see cref="FuncTemplate{TControl, TParam}"/> class.
/// </summary> /// </summary>
/// <param name="func">The function used to create the control.</param> /// <param name="func">The function used to create the control.</param>
public FuncTemplate(Func<TParam, TControl> func) public FuncTemplate(Func<TParam, INameScope, TControl> func)
{ {
Contract.Requires<ArgumentNullException>(func != null); Contract.Requires<ArgumentNullException>(func != null);
@ -35,7 +35,12 @@ namespace Avalonia.Controls.Templates
/// </returns> /// </returns>
public TControl Build(TParam param) public TControl Build(TParam param)
{ {
return _func(param); var scope = new NameScope();
var rv = _func(param, scope);
// TODO: May be return the name scope alongside with the control instead?
if (rv is StyledElement sl)
NameScope.SetNameScope(sl, scope);
return rv;
} }
} }
} }

4
src/Avalonia.Controls/Templates/FuncTreeDataTemplate.cs

@ -28,7 +28,7 @@ namespace Avalonia.Controls.Templates
/// </param> /// </param>
public FuncTreeDataTemplate( public FuncTreeDataTemplate(
Type type, Type type,
Func<object, IControl> build, Func<object, INameScope, IControl> build,
Func<object, IEnumerable> itemsSelector) Func<object, IEnumerable> itemsSelector)
: this(o => IsInstance(o, type), build, itemsSelector) : this(o => IsInstance(o, type), build, itemsSelector)
{ {
@ -48,7 +48,7 @@ namespace Avalonia.Controls.Templates
/// </param> /// </param>
public FuncTreeDataTemplate( public FuncTreeDataTemplate(
Func<object, bool> match, Func<object, bool> match,
Func<object, IControl> build, Func<object, INameScope, IControl> build,
Func<object, IEnumerable> itemsSelector) Func<object, IEnumerable> itemsSelector)
: base(match, build) : base(match, build)
{ {

15
src/Avalonia.Controls/Templates/FuncTreeDataTemplate`1.cs

@ -23,7 +23,7 @@ namespace Avalonia.Controls.Templates
/// items. /// items.
/// </param> /// </param>
public FuncTreeDataTemplate( public FuncTreeDataTemplate(
Func<T, Control> build, Func<T, INameScope, Control> build,
Func<T, IEnumerable> itemsSelector) Func<T, IEnumerable> itemsSelector)
: base( : base(
typeof(T), typeof(T),
@ -46,7 +46,7 @@ namespace Avalonia.Controls.Templates
/// </param> /// </param>
public FuncTreeDataTemplate( public FuncTreeDataTemplate(
Func<T, bool> match, Func<T, bool> match,
Func<T, Control> build, Func<T, INameScope, Control> build,
Func<T, IEnumerable> itemsSelector) Func<T, IEnumerable> itemsSelector)
: base( : base(
CastMatch(match), CastMatch(match),
@ -65,6 +65,17 @@ namespace Avalonia.Controls.Templates
return o => (o is T) && f((T)o); return o => (o is T) && f((T)o);
} }
/// <summary>
/// Casts a function with a typed parameter to an untyped function.
/// </summary>
/// <typeparam name="TResult">The result.</typeparam>
/// <param name="f">The typed function.</param>
/// <returns>The untyped function.</returns>
private static Func<object, INameScope, TResult> Cast<TResult>(Func<T, INameScope, TResult> f)
{
return (o, s) => f((T)o, s);
}
/// <summary> /// <summary>
/// Casts a function with a typed parameter to an untyped function. /// Casts a function with a typed parameter to an untyped function.
/// </summary> /// </summary>

34
src/Avalonia.Controls/UserControl.cs

@ -9,40 +9,8 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Provides the base class for defining a new control that encapsulates related existing controls and provides its own logic. /// Provides the base class for defining a new control that encapsulates related existing controls and provides its own logic.
/// </summary> /// </summary>
public class UserControl : ContentControl, IStyleable, INameScope public class UserControl : ContentControl, IStyleable
{ {
private readonly NameScope _nameScope = new NameScope();
/// <inheritdoc/>
event EventHandler<NameScopeEventArgs> INameScope.Registered
{
add { _nameScope.Registered += value; }
remove { _nameScope.Registered -= value; }
}
/// <inheritdoc/>
event EventHandler<NameScopeEventArgs> INameScope.Unregistered
{
add { _nameScope.Unregistered += value; }
remove { _nameScope.Unregistered -= value; }
}
/// <inheritdoc/>
void INameScope.Register(string name, object element)
{
_nameScope.Register(name, element);
}
/// <inheritdoc/>
object INameScope.Find(string name)
{
return _nameScope.Find(name);
}
/// <inheritdoc/>
void INameScope.Unregister(string name)
{
_nameScope.Unregister(name);
}
} }
} }

34
src/Avalonia.Controls/Window.cs

@ -48,7 +48,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// A top-level window. /// A top-level window.
/// </summary> /// </summary>
public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot, INameScope public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot
{ {
/// <summary> /// <summary>
/// Defines the <see cref="SizeToContent"/> property. /// Defines the <see cref="SizeToContent"/> property.
@ -157,20 +157,6 @@ namespace Avalonia.Controls
_maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size); _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size);
} }
/// <inheritdoc/>
event EventHandler<NameScopeEventArgs> INameScope.Registered
{
add { _nameScope.Registered += value; }
remove { _nameScope.Registered -= value; }
}
/// <inheritdoc/>
event EventHandler<NameScopeEventArgs> INameScope.Unregistered
{
add { _nameScope.Unregistered += value; }
remove { _nameScope.Unregistered -= value; }
}
/// <summary> /// <summary>
/// Gets the platform-specific window implementation. /// Gets the platform-specific window implementation.
/// </summary> /// </summary>
@ -494,24 +480,6 @@ namespace Avalonia.Controls
} }
} }
/// <inheritdoc/>
void INameScope.Register(string name, object element)
{
_nameScope.Register(name, element);
}
/// <inheritdoc/>
object INameScope.Find(string name)
{
return _nameScope.Find(name);
}
/// <inheritdoc/>
void INameScope.Unregister(string name)
{
_nameScope.Unregister(name);
}
/// <inheritdoc/> /// <inheritdoc/>
protected override Size MeasureOverride(Size availableSize) protected override Size MeasureOverride(Size availableSize)
{ {

4
src/Avalonia.ReactiveUI/AutoDataTemplateBindingHook.cs

@ -16,7 +16,7 @@ namespace Avalonia.ReactiveUI
/// </summary> /// </summary>
public class AutoDataTemplateBindingHook : IPropertyBindingHook public class AutoDataTemplateBindingHook : IPropertyBindingHook
{ {
private static FuncDataTemplate DefaultItemTemplate = new FuncDataTemplate<object>(x => private static FuncDataTemplate DefaultItemTemplate = new FuncDataTemplate<object>((x, _) =>
{ {
var control = new ViewModelViewHost(); var control = new ViewModelViewHost();
var context = control.GetObservable(Control.DataContextProperty); var context = control.GetObservable(Control.DataContextProperty);
@ -52,4 +52,4 @@ namespace Avalonia.ReactiveUI
return true; return true;
} }
} }
} }

15
src/Avalonia.Styling/Controls/NameScope.cs

@ -106,6 +106,21 @@ namespace Avalonia.Controls
} }
} }
/// <summary>
/// Registers an element in the name scope associated with the scopeElement.
/// Creates the scope if one isn't associated with the element yet
/// </summary>
/// <param name="scopeElement"></param>
/// <param name="name"></param>
/// <param name="element"></param>
public static void Register(StyledElement scopeElement, string name, object element)
{
var scope = scopeElement as INameScope ?? GetNameScope(scopeElement);
if(scope == null)
SetNameScope(scopeElement, scope = new NameScope());
scope.Register(name, element);
}
/// <summary> /// <summary>
/// Finds a named element in the name scope. /// Finds a named element in the name scope.
/// </summary> /// </summary>

41
src/Avalonia.Styling/Controls/NameScopeExtensions.cs

@ -37,6 +37,25 @@ namespace Avalonia.Controls
return (T)result; return (T)result;
} }
/// <summary>
/// Finds a named element in an <see cref="INameScope"/>.
/// </summary>
/// <typeparam name="T">The element type.</typeparam>
/// <param name="anchor">The control to take the name scope from.</param>
/// <param name="name">The name.</param>
/// <returns>The named element or null if not found.</returns>
public static T Find<T>(this ILogical anchor, string name)
where T : class
{
Contract.Requires<ArgumentNullException>(anchor != null);
Contract.Requires<ArgumentNullException>(name != null);
var styledAnchor = anchor as StyledElement;
if (styledAnchor == null)
return null;
var nameScope = (anchor as INameScope) ?? NameScope.GetNameScope(styledAnchor);
return nameScope?.Find<T>(name);
}
/// <summary> /// <summary>
/// Gets a named element from an <see cref="INameScope"/> or throws if no element of the /// Gets a named element from an <see cref="INameScope"/> or throws if no element of the
/// requested name was found. /// requested name was found.
@ -67,6 +86,28 @@ namespace Avalonia.Controls
return (T)result; return (T)result;
} }
/// <summary>
/// Gets a named element from an <see cref="INameScope"/> or throws if no element of the
/// requested name was found.
/// </summary>
/// <typeparam name="T">The element type.</typeparam>
/// <param name="anchor">The control to take the name scope from.</param>
/// <param name="name">The name.</param>
/// <returns>The named element.</returns>
public static T Get<T>(this ILogical anchor, string name)
where T : class
{
Contract.Requires<ArgumentNullException>(anchor != null);
Contract.Requires<ArgumentNullException>(name != null);
var nameScope = (anchor as INameScope) ?? NameScope.GetNameScope((StyledElement)anchor);
if (nameScope == null)
throw new InvalidOperationException(
"The control doesn't have an associated name scope, probably no registrations has been done yet");
return nameScope.Get<T>(name);
}
public static INameScope FindNameScope(this ILogical control) public static INameScope FindNameScope(this ILogical control)
{ {
Contract.Requires<ArgumentNullException>(control != null); Contract.Requires<ArgumentNullException>(control != null);

21
src/Avalonia.Styling/StyledElement.cs

@ -61,7 +61,6 @@ namespace Avalonia
private readonly Classes _classes = new Classes(); private readonly Classes _classes = new Classes();
private bool _isAttachedToLogicalTree; private bool _isAttachedToLogicalTree;
private IAvaloniaList<ILogical> _logicalChildren; private IAvaloniaList<ILogical> _logicalChildren;
private INameScope _nameScope;
private IResourceDictionary _resources; private IResourceDictionary _resources;
private Styles _styles; private Styles _styles;
private bool _styled; private bool _styled;
@ -82,7 +81,6 @@ namespace Avalonia
/// </summary> /// </summary>
public StyledElement() public StyledElement()
{ {
_nameScope = this as INameScope;
_isAttachedToLogicalTree = this is IStyleRoot; _isAttachedToLogicalTree = this is IStyleRoot;
} }
@ -381,7 +379,6 @@ namespace Avalonia
{ {
if (_initCount == 0 && (!_styled || force)) if (_initCount == 0 && (!_styled || force))
{ {
RegisterWithNameScope();
ApplyStyling(); ApplyStyling();
_styled = true; _styled = true;
} }
@ -675,19 +672,6 @@ namespace Avalonia
AvaloniaLocator.Current.GetService<IStyler>()?.ApplyStyles(this); AvaloniaLocator.Current.GetService<IStyler>()?.ApplyStyles(this);
} }
private void RegisterWithNameScope()
{
if (_nameScope == null)
{
_nameScope = NameScope.GetNameScope(this) ?? ((StyledElement)Parent)?._nameScope;
}
if (Name != null)
{
_nameScope?.Register(Name, this);
}
}
private static void ValidateLogicalChild(ILogical c) private static void ValidateLogicalChild(ILogical c)
{ {
if (c == null) if (c == null)
@ -724,11 +708,6 @@ namespace Avalonia
{ {
if (_isAttachedToLogicalTree) if (_isAttachedToLogicalTree)
{ {
if (Name != null)
{
_nameScope?.Unregister(Name);
}
_isAttachedToLogicalTree = false; _isAttachedToLogicalTree = false;
_styleDetach.OnNext(this); _styleDetach.OnNext(this);
OnDetachedFromLogicalTree(e); OnDetachedFromLogicalTree(e);

1
src/Avalonia.Styling/Styling/Setter.cs

@ -99,7 +99,6 @@ namespace Avalonia.Styling
if (template != null && !isPropertyOfTypeITemplate) if (template != null && !isPropertyOfTypeITemplate)
{ {
var materialized = template.Build(); var materialized = template.Build();
NameScope.SetNameScope((StyledElement)materialized, new NameScope());
value = materialized; value = materialized;
} }

1
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs

@ -35,6 +35,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}, },
ProvideValueTarget = typeSystem.GetType("Avalonia.Markup.Xaml.IProvideValueTarget"), ProvideValueTarget = typeSystem.GetType("Avalonia.Markup.Xaml.IProvideValueTarget"),
RootObjectProvider = typeSystem.GetType("Avalonia.Markup.Xaml.IRootObjectProvider"), RootObjectProvider = typeSystem.GetType("Avalonia.Markup.Xaml.IRootObjectProvider"),
RootObjectProviderIntermediateRootPropertyName = "IntermediateRootObject",
UriContextProvider = typeSystem.GetType("Avalonia.Markup.Xaml.IUriContext"), UriContextProvider = typeSystem.GetType("Avalonia.Markup.Xaml.IUriContext"),
ParentStackProvider = ParentStackProvider =
typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.IAvaloniaXamlIlParentStackProvider"), typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.IAvaloniaXamlIlParentStackProvider"),

69
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AddNameScopeRegistration.cs

@ -15,7 +15,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
&& pa.Property.DeclaringType.FullName == "Avalonia.StyledElement") && pa.Property.DeclaringType.FullName == "Avalonia.StyledElement")
{ {
if (context.ParentNodes().FirstOrDefault() is XamlIlManipulationGroupNode mg if (context.ParentNodes().FirstOrDefault() is XamlIlManipulationGroupNode mg
&& mg.Children.OfType<ScopeRegistrationNode>().Any()) && mg.Children.OfType<AvaloniaNameScopeRegistrationXamlIlNode>().Any())
return node; return node;
IXamlIlAstValueNode value = null; IXamlIlAstValueNode value = null;
@ -41,7 +41,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
Children = Children =
{ {
pa, pa,
new ScopeRegistrationNode(value) new AvaloniaNameScopeRegistrationXamlIlNode(value, context.GetAvaloniaTypes())
} }
}; };
} }
@ -49,46 +49,41 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return node; return node;
} }
class ScopeRegistrationNode : XamlIlAstNode, IXamlIlAstManipulationNode, IXamlIlAstEmitableNode
}
class AvaloniaNameScopeRegistrationXamlIlNode : XamlIlAstNode, IXamlIlAstManipulationNode, IXamlIlAstEmitableNode
{
private readonly AvaloniaXamlIlWellKnownTypes _types;
public IXamlIlAstValueNode Name { get; set; }
public AvaloniaNameScopeRegistrationXamlIlNode(IXamlIlAstValueNode name, AvaloniaXamlIlWellKnownTypes types) : base(name)
{ {
public IXamlIlAstValueNode Value { get; set; } _types = types;
public ScopeRegistrationNode(IXamlIlAstValueNode value) : base(value) Name = name;
{ }
Value = value;
}
public override void VisitChildren(IXamlIlAstVisitor visitor) public override void VisitChildren(IXamlIlAstVisitor visitor)
=> Value = (IXamlIlAstValueNode)Value.Visit(visitor); => Name = (IXamlIlAstValueNode)Name.Visit(visitor);
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen) public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen)
{
using (var targetLoc = context.GetLocal(context.Configuration.WellKnownTypes.Object))
{ {
var exts = context.Configuration.TypeSystem.GetType("Avalonia.Controls.NameScopeExtensions"); codeGen
var findNameScope = exts.FindMethod(m => m.Name == "FindNameScope"); // var target = {pop}
var registerMethod = findNameScope.ReturnType.FindMethod(m => m.Name == "Register"); .Stloc(targetLoc.Local)
using (var targetLoc = context.GetLocal(context.Configuration.WellKnownTypes.Object)) // NameScope.Register(context.IntermediateRoot, Name, target)
using (var nameScopeLoc = context.GetLocal(findNameScope.ReturnType)) .Ldloc(context.ContextLocal)
{ .Ldfld(context.RuntimeContext.IntermediateRootObjectField)
var exit = codeGen.DefineLabel(); .Castclass(_types.StyledElement);
codeGen context.Emit(Name, codeGen, Name.Type.GetClrType());
// var target = {pop} codeGen
.Stloc(targetLoc.Local) .Ldloc(targetLoc.Local)
// var scope = target.FindNameScope() .EmitCall(_types.NameScopeStaticRegister, true);
.Ldloc(targetLoc.Local)
.Castclass(findNameScope.Parameters[0])
.EmitCall(findNameScope)
.Stloc(nameScopeLoc.Local)
// if({scope} != null) goto call;
.Ldloc(nameScopeLoc.Local)
.Brfalse(exit)
.Ldloc(nameScopeLoc.Local);
context.Emit(Value, codeGen, Value.Type.GetClrType());
codeGen
.Ldloc(targetLoc.Local)
.EmitCall(registerMethod)
.MarkLabel(exit);
}
return XamlIlNodeEmitResult.Void(1);
} }
return XamlIlNodeEmitResult.Void(1);
} }
} }
} }

12
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs

@ -19,6 +19,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlIlType Transitions { get; } public IXamlIlType Transitions { get; }
public IXamlIlType AssignBindingAttribute { get; } public IXamlIlType AssignBindingAttribute { get; }
public IXamlIlType UnsetValueType { get; } public IXamlIlType UnsetValueType { get; }
public IXamlIlType StyledElement { get; }
public IXamlIlType NameScope { get; }
public IXamlIlMethod NameScopeStaticRegister { get; }
public AvaloniaXamlIlWellKnownTypes(XamlIlAstTransformationContext ctx) public AvaloniaXamlIlWellKnownTypes(XamlIlAstTransformationContext ctx)
{ {
@ -37,6 +40,15 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
AvaloniaProperty, AvaloniaProperty,
IBinding, ctx.Configuration.WellKnownTypes.Object); IBinding, ctx.Configuration.WellKnownTypes.Object);
UnsetValueType = ctx.Configuration.TypeSystem.GetType("Avalonia.UnsetValueType"); UnsetValueType = ctx.Configuration.TypeSystem.GetType("Avalonia.UnsetValueType");
StyledElement = ctx.Configuration.TypeSystem.GetType("Avalonia.StyledElement");
NameScope = ctx.Configuration.TypeSystem.GetType("Avalonia.Controls.NameScope");
NameScopeStaticRegister = NameScope.FindMethod(
new FindMethodMethodSignature("Register", XamlIlTypes.Void,
StyledElement, XamlIlTypes.String, XamlIlTypes.Object)
{
IsStatic = true, DeclaringOnly = true, IsExactMatch = true
});
AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", XamlIlTypes.Void, AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", XamlIlTypes.Void,
false, AvaloniaProperty, XamlIlTypes.Object, BindingPriority); false, AvaloniaProperty, XamlIlTypes.Object, BindingPriority);
} }

1
src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs

@ -56,6 +56,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
} }
public object RootObject { get; } public object RootObject { get; }
public object IntermediateRootObject => RootObject;
} }

2
src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github

@ -1 +1 @@
Subproject commit 894b2c02827fd5eb16a338de5d5b6c9fbc60fef5 Subproject commit fc52295ea6c45f709bf63975026a4a18ce230be9

8
src/Markup/Avalonia.Markup.Xaml/XamlTypes.cs

@ -10,7 +10,15 @@ namespace Avalonia.Markup.Xaml
public interface IRootObjectProvider public interface IRootObjectProvider
{ {
/// <summary>
/// The root object of the xaml file
/// </summary>
object RootObject { get; } object RootObject { get; }
/// <summary>
/// The "current" root object, contains either the root of the xaml file
/// or the root object of the control/data template
/// </summary>
object IntermediateRootObject { get; }
} }
public interface IUriContext public interface IUriContext

10
tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs

@ -1012,25 +1012,25 @@ namespace Avalonia.Controls.UnitTests
} }
private IControlTemplate CreateTemplate() private IControlTemplate CreateTemplate()
{ {
return new FuncControlTemplate<AutoCompleteBox>(control => return new FuncControlTemplate<AutoCompleteBox>((control, scope) =>
{ {
var textBox = var textBox =
new TextBox new TextBox
{ {
Name = "PART_TextBox" Name = "PART_TextBox"
}; }.RegisterInNameScope(scope);
var listbox = var listbox =
new ListBox new ListBox
{ {
Name = "PART_SelectingItemsControl" Name = "PART_SelectingItemsControl"
}; }.RegisterInNameScope(scope);
var popup = var popup =
new Popup new Popup
{ {
Name = "PART_Popup" Name = "PART_Popup"
}; }.RegisterInNameScope(scope);
var panel = new Panel(); var panel = new Panel().WithNameScope(scope);
panel.Children.Add(textBox); panel.Children.Add(textBox);
panel.Children.Add(popup); panel.Children.Add(popup);
panel.Children.Add(listbox); panel.Children.Add(listbox);

4
tests/Avalonia.Controls.UnitTests/CarouselTests.cs

@ -302,7 +302,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal("FooBar", target.SelectedItem); Assert.Equal("FooBar", target.SelectedItem);
} }
private Control CreateTemplate(Carousel control) private Control CreateTemplate(Carousel control, INameScope scope)
{ {
return new CarouselPresenter return new CarouselPresenter
{ {
@ -312,7 +312,7 @@ namespace Avalonia.Controls.UnitTests
[~CarouselPresenter.ItemsPanelProperty] = control[~Carousel.ItemsPanelProperty], [~CarouselPresenter.ItemsPanelProperty] = control[~Carousel.ItemsPanelProperty],
[~CarouselPresenter.SelectedIndexProperty] = control[~Carousel.SelectedIndexProperty], [~CarouselPresenter.SelectedIndexProperty] = control[~Carousel.SelectedIndexProperty],
[~CarouselPresenter.PageTransitionProperty] = control[~Carousel.PageTransitionProperty], [~CarouselPresenter.PageTransitionProperty] = control[~Carousel.PageTransitionProperty],
}; }.RegisterInNameScope(scope).WithNameScope(scope);
} }
} }
} }

10
tests/Avalonia.Controls.UnitTests/ComboBoxTests.cs

@ -80,7 +80,7 @@ namespace Avalonia.Controls.UnitTests
private FuncControlTemplate GetTemplate() private FuncControlTemplate GetTemplate()
{ {
return new FuncControlTemplate<ComboBox>(parent => return new FuncControlTemplate<ComboBox>((parent, scope) =>
{ {
return new Panel return new Panel
{ {
@ -94,7 +94,7 @@ namespace Avalonia.Controls.UnitTests
new ToggleButton new ToggleButton
{ {
Name = "toggle", Name = "toggle",
}, }.RegisterInNameScope(scope),
new Popup new Popup
{ {
Name = "PART_Popup", Name = "PART_Popup",
@ -102,10 +102,10 @@ namespace Avalonia.Controls.UnitTests
{ {
Name = "PART_ItemsPresenter", Name = "PART_ItemsPresenter",
[!ItemsPresenter.ItemsProperty] = parent[!ComboBox.ItemsProperty], [!ItemsPresenter.ItemsProperty] = parent[!ComboBox.ItemsProperty],
} }.RegisterInNameScope(scope)
} }.RegisterInNameScope(scope)
} }
}; }.WithNameScope(scope);
}); });
} }
} }

12
tests/Avalonia.Controls.UnitTests/ContentControlTests.cs

@ -126,7 +126,7 @@ namespace Avalonia.Controls.UnitTests
var target = new ContentControl var target = new ContentControl
{ {
Template = GetTemplate(), Template = GetTemplate(),
ContentTemplate = new FuncDataTemplate<string>(_ => new Canvas()), ContentTemplate = new FuncDataTemplate<string>((_, __) => new Canvas()),
}; };
target.Content = "Foo"; target.Content = "Foo";
@ -302,8 +302,8 @@ namespace Avalonia.Controls.UnitTests
var target = new ContentControl var target = new ContentControl
{ {
Template = new FuncControlTemplate<ContentControl>(_ => presenter), Template = new FuncControlTemplate<ContentControl>((_, __) => presenter),
ContentTemplate = new FuncDataTemplate<string>(x => new Canvas()), ContentTemplate = new FuncDataTemplate<string>((_, __) => new Canvas()),
Content = "foo", Content = "foo",
}; };
@ -333,7 +333,7 @@ namespace Avalonia.Controls.UnitTests
private FuncControlTemplate GetTemplate() private FuncControlTemplate GetTemplate()
{ {
return new FuncControlTemplate<ContentControl>(parent => return new FuncControlTemplate<ContentControl>((parent, scope) =>
{ {
return new Border return new Border
{ {
@ -343,8 +343,8 @@ namespace Avalonia.Controls.UnitTests
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty], [~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty],
[~ContentPresenter.ContentTemplateProperty] = parent[~ContentControl.ContentTemplateProperty], [~ContentPresenter.ContentTemplateProperty] = parent[~ContentControl.ContentTemplateProperty],
} }.RegisterInNameScope(scope)
}; }.WithNameScope(scope);
}); });
} }
} }

12
tests/Avalonia.Controls.UnitTests/DatePickerTests.cs

@ -93,30 +93,30 @@ namespace Avalonia.Controls.UnitTests
private IControlTemplate CreateTemplate() private IControlTemplate CreateTemplate()
{ {
return new FuncControlTemplate<DatePicker>(control => return new FuncControlTemplate<DatePicker>((control, scope) =>
{ {
var textBox = var textBox =
new TextBox new TextBox
{ {
Name = "PART_TextBox" Name = "PART_TextBox"
}; }.RegisterInNameScope(scope);
var button = var button =
new Button new Button
{ {
Name = "PART_Button" Name = "PART_Button"
}; }.RegisterInNameScope(scope);
var calendar = var calendar =
new Calendar new Calendar
{ {
Name = "PART_Calendar" Name = "PART_Calendar"
}; }.RegisterInNameScope(scope);
var popup = var popup =
new Popup new Popup
{ {
Name = "PART_Popup" Name = "PART_Popup"
}; }.RegisterInNameScope(scope);
var panel = new Panel(); var panel = new Panel().WithNameScope(scope);
panel.Children.Add(textBox); panel.Children.Add(textBox);
panel.Children.Add(button); panel.Children.Add(button);
panel.Children.Add(popup); panel.Children.Add(popup);

21
tests/Avalonia.Controls.UnitTests/GridSplitterTests.cs

@ -20,6 +20,7 @@ namespace Avalonia.Controls.UnitTests
[Fact] [Fact]
public void Detects_Horizontal_Orientation() public void Detects_Horizontal_Orientation()
{ {
GridSplitter splitter;
var grid = new Grid() var grid = new Grid()
{ {
RowDefinitions = new RowDefinitions("*,Auto,*"), RowDefinitions = new RowDefinitions("*,Auto,*"),
@ -27,7 +28,7 @@ namespace Avalonia.Controls.UnitTests
Children = Children =
{ {
new Border { [Grid.RowProperty] = 0 }, new Border { [Grid.RowProperty] = 0 },
new GridSplitter { [Grid.RowProperty] = 1, Name = "splitter" }, (splitter = new GridSplitter { [Grid.RowProperty] = 1 }),
new Border { [Grid.RowProperty] = 2 } new Border { [Grid.RowProperty] = 2 }
} }
}; };
@ -35,12 +36,13 @@ namespace Avalonia.Controls.UnitTests
var root = new TestRoot { Child = grid }; var root = new TestRoot { Child = grid };
root.Measure(new Size(100, 300)); root.Measure(new Size(100, 300));
root.Arrange(new Rect(0, 0, 100, 300)); root.Arrange(new Rect(0, 0, 100, 300));
Assert.Contains(grid.FindControl<GridSplitter>("splitter").Classes, ":horizontal".Equals); Assert.Contains(splitter.Classes, ":horizontal".Equals);
} }
[Fact] [Fact]
public void Detects_Vertical_Orientation() public void Detects_Vertical_Orientation()
{ {
GridSplitter splitter;
var grid = new Grid() var grid = new Grid()
{ {
ColumnDefinitions = new ColumnDefinitions("*,Auto,*"), ColumnDefinitions = new ColumnDefinitions("*,Auto,*"),
@ -48,7 +50,7 @@ namespace Avalonia.Controls.UnitTests
Children = Children =
{ {
new Border { [Grid.ColumnProperty] = 0 }, new Border { [Grid.ColumnProperty] = 0 },
new GridSplitter { [Grid.ColumnProperty] = 1, Name = "splitter" }, (splitter = new GridSplitter { [Grid.ColumnProperty] = 1}),
new Border { [Grid.ColumnProperty] = 2 }, new Border { [Grid.ColumnProperty] = 2 },
} }
}; };
@ -56,12 +58,13 @@ namespace Avalonia.Controls.UnitTests
var root = new TestRoot { Child = grid }; var root = new TestRoot { Child = grid };
root.Measure(new Size(100, 300)); root.Measure(new Size(100, 300));
root.Arrange(new Rect(0, 0, 100, 300)); root.Arrange(new Rect(0, 0, 100, 300));
Assert.Contains(grid.FindControl<GridSplitter>("splitter").Classes, ":vertical".Equals); Assert.Contains(splitter.Classes, ":vertical".Equals);
} }
[Fact] [Fact]
public void Detects_With_Both_Auto() public void Detects_With_Both_Auto()
{ {
GridSplitter splitter;
var grid = new Grid() var grid = new Grid()
{ {
ColumnDefinitions = new ColumnDefinitions("Auto,Auto,Auto"), ColumnDefinitions = new ColumnDefinitions("Auto,Auto,Auto"),
@ -69,7 +72,7 @@ namespace Avalonia.Controls.UnitTests
Children = Children =
{ {
new Border { [Grid.ColumnProperty] = 0 }, new Border { [Grid.ColumnProperty] = 0 },
new GridSplitter { [Grid.ColumnProperty] = 1, Name = "splitter" }, (splitter = new GridSplitter { [Grid.ColumnProperty] = 1}),
new Border { [Grid.ColumnProperty] = 2 }, new Border { [Grid.ColumnProperty] = 2 },
} }
}; };
@ -77,7 +80,7 @@ namespace Avalonia.Controls.UnitTests
var root = new TestRoot { Child = grid }; var root = new TestRoot { Child = grid };
root.Measure(new Size(100, 300)); root.Measure(new Size(100, 300));
root.Arrange(new Rect(0, 0, 100, 300)); root.Arrange(new Rect(0, 0, 100, 300));
Assert.Contains(grid.FindControl<GridSplitter>("splitter").Classes, ":vertical".Equals); Assert.Contains(splitter.Classes, ":vertical".Equals);
} }
[Fact] [Fact]
@ -129,13 +132,14 @@ namespace Avalonia.Controls.UnitTests
[Fact] [Fact]
public void In_First_Position_Doesnt_Throw_Exception() public void In_First_Position_Doesnt_Throw_Exception()
{ {
GridSplitter splitter;
var grid = new Grid() var grid = new Grid()
{ {
ColumnDefinitions = new ColumnDefinitions("Auto,*,*"), ColumnDefinitions = new ColumnDefinitions("Auto,*,*"),
RowDefinitions = new RowDefinitions("*,*"), RowDefinitions = new RowDefinitions("*,*"),
Children = Children =
{ {
new GridSplitter { [Grid.ColumnProperty] = 0, Name = "splitter" }, (splitter = new GridSplitter { [Grid.ColumnProperty] = 0} ),
new Border { [Grid.ColumnProperty] = 1 }, new Border { [Grid.ColumnProperty] = 1 },
new Border { [Grid.ColumnProperty] = 2 }, new Border { [Grid.ColumnProperty] = 2 },
} }
@ -144,7 +148,6 @@ namespace Avalonia.Controls.UnitTests
var root = new TestRoot { Child = grid }; var root = new TestRoot { Child = grid };
root.Measure(new Size(100, 300)); root.Measure(new Size(100, 300));
root.Arrange(new Rect(0, 0, 100, 300)); root.Arrange(new Rect(0, 0, 100, 300));
var splitter = grid.FindControl<GridSplitter>("splitter");
splitter.RaiseEvent(new VectorEventArgs splitter.RaiseEvent(new VectorEventArgs
{ {
RoutedEvent = Thumb.DragDeltaEvent, RoutedEvent = Thumb.DragDeltaEvent,
@ -199,4 +202,4 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(columnDefinitions[2].Width, new GridLength(80, GridUnitType.Star)); Assert.Equal(columnDefinitions[2].Width, new GridLength(80, GridUnitType.Star));
} }
} }
} }

6
tests/Avalonia.Controls.UnitTests/HeaderedItemsControlTests .cs

@ -63,7 +63,7 @@ namespace Avalonia.Controls.UnitTests
private FuncControlTemplate GetTemplate() private FuncControlTemplate GetTemplate()
{ {
return new FuncControlTemplate<HeaderedItemsControl>(parent => return new FuncControlTemplate<HeaderedItemsControl>((parent, scope) =>
{ {
return new Border return new Border
{ {
@ -71,8 +71,8 @@ namespace Avalonia.Controls.UnitTests
{ {
Name = "PART_HeaderPresenter", Name = "PART_HeaderPresenter",
[~ContentPresenter.ContentProperty] = parent[~HeaderedItemsControl.HeaderProperty], [~ContentPresenter.ContentProperty] = parent[~HeaderedItemsControl.HeaderProperty],
} }.RegisterInNameScope(scope)
}; }.WithNameScope(scope);
}); });
} }
} }

10
tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs

@ -23,7 +23,7 @@ namespace Avalonia.Controls.UnitTests
var target = new ItemsControl var target = new ItemsControl
{ {
Template = GetTemplate(), Template = GetTemplate(),
ItemTemplate = new FuncDataTemplate<string>(_ => new Canvas()), ItemTemplate = new FuncDataTemplate<string>((_, __) => new Canvas()),
}; };
target.Items = new[] { "Foo" }; target.Items = new[] { "Foo" };
@ -411,7 +411,7 @@ namespace Avalonia.Controls.UnitTests
DataContext = "Base", DataContext = "Base",
DataTemplates = DataTemplates =
{ {
new FuncDataTemplate<Item>(x => new Button { Content = x }) new FuncDataTemplate<Item>((x, __) => new Button { Content = x })
}, },
Items = items, Items = items,
}; };
@ -578,7 +578,7 @@ namespace Avalonia.Controls.UnitTests
private FuncControlTemplate GetTemplate() private FuncControlTemplate GetTemplate()
{ {
return new FuncControlTemplate<ItemsControl>(parent => return new FuncControlTemplate<ItemsControl>((parent, scope) =>
{ {
return new Border return new Border
{ {
@ -588,8 +588,8 @@ namespace Avalonia.Controls.UnitTests
Name = "PART_ItemsPresenter", Name = "PART_ItemsPresenter",
MemberSelector = parent.MemberSelector, MemberSelector = parent.MemberSelector,
[~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty], [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
} }.RegisterInNameScope(scope)
}; }.WithNameScope(scope);
}); });
} }

30
tests/Avalonia.Controls.UnitTests/ListBoxTests.cs

@ -25,7 +25,7 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = ListBoxTemplate(), Template = ListBoxTemplate(),
Items = new[] { "Foo" }, Items = new[] { "Foo" },
ItemTemplate = new FuncDataTemplate<string>(_ => new Canvas()), ItemTemplate = new FuncDataTemplate<string>((_, __) => new Canvas()),
}; };
Prepare(target); Prepare(target);
@ -113,7 +113,7 @@ namespace Avalonia.Controls.UnitTests
DataContext = "Base", DataContext = "Base",
DataTemplates = DataTemplates =
{ {
new FuncDataTemplate<Item>(x => new Button { Content = x }) new FuncDataTemplate<Item>((x, _) => new Button { Content = x })
}, },
Items = items, Items = items,
}; };
@ -138,7 +138,7 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = ListBoxTemplate(), Template = ListBoxTemplate(),
Items = Enumerable.Range(0, 20).Select(x => $"Item {x}").ToList(), Items = Enumerable.Range(0, 20).Select(x => $"Item {x}").ToList(),
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Height = 10 }), ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Height = 10 }),
SelectedIndex = 0, SelectedIndex = 0,
}; };
@ -162,7 +162,7 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = ListBoxTemplate(), Template = ListBoxTemplate(),
Items = Enumerable.Range(0, 20).Select(x => $"Item {x}").ToList(), Items = Enumerable.Range(0, 20).Select(x => $"Item {x}").ToList(),
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Width = 20, Height = 10 }), ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
SelectedIndex = 0, SelectedIndex = 0,
}; };
@ -181,7 +181,7 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = ListBoxTemplate(), Template = ListBoxTemplate(),
Items = items, Items = items,
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Width = 20, Height = 10 }), ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
SelectedIndex = 0, SelectedIndex = 0,
}; };
@ -205,7 +205,7 @@ namespace Avalonia.Controls.UnitTests
Template = ListBoxTemplate(), Template = ListBoxTemplate(),
Items = items, Items = items,
SelectionMode = SelectionMode.Toggle, SelectionMode = SelectionMode.Toggle,
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Height = 10 }) ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Height = 10 })
}; };
Prepare(target); Prepare(target);
@ -239,7 +239,7 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = ListBoxTemplate(), Template = ListBoxTemplate(),
Items = items, Items = items,
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Height = 11 }) ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Height = 11 })
}; };
Prepare(target); Prepare(target);
@ -287,7 +287,7 @@ namespace Avalonia.Controls.UnitTests
target.DataContext = items; target.DataContext = items;
target.VirtualizationMode = virtualizationMode; target.VirtualizationMode = virtualizationMode;
target.ItemTemplate = new FuncDataTemplate<object>(c => target.ItemTemplate = new FuncDataTemplate<object>((c, _) =>
{ {
var tb = new TextBlock() { Height = 10, Width = 30 }; var tb = new TextBlock() { Height = 10, Width = 30 };
tb.Bind(TextBlock.TextProperty, new Data.Binding()); tb.Bind(TextBlock.TextProperty, new Data.Binding());
@ -334,7 +334,7 @@ namespace Avalonia.Controls.UnitTests
private FuncControlTemplate ListBoxTemplate() private FuncControlTemplate ListBoxTemplate()
{ {
return new FuncControlTemplate<ListBox>(parent => return new FuncControlTemplate<ListBox>((parent, scope) =>
new ScrollViewer new ScrollViewer
{ {
Name = "PART_ScrollViewer", Name = "PART_ScrollViewer",
@ -345,24 +345,24 @@ namespace Avalonia.Controls.UnitTests
[~ItemsPresenter.ItemsProperty] = parent.GetObservable(ItemsControl.ItemsProperty).ToBinding(), [~ItemsPresenter.ItemsProperty] = parent.GetObservable(ItemsControl.ItemsProperty).ToBinding(),
[~ItemsPresenter.ItemsPanelProperty] = parent.GetObservable(ItemsControl.ItemsPanelProperty).ToBinding(), [~ItemsPresenter.ItemsPanelProperty] = parent.GetObservable(ItemsControl.ItemsPanelProperty).ToBinding(),
[~ItemsPresenter.VirtualizationModeProperty] = parent.GetObservable(ListBox.VirtualizationModeProperty).ToBinding(), [~ItemsPresenter.VirtualizationModeProperty] = parent.GetObservable(ListBox.VirtualizationModeProperty).ToBinding(),
} }.RegisterInNameScope(scope)
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private FuncControlTemplate ListBoxItemTemplate() private FuncControlTemplate ListBoxItemTemplate()
{ {
return new FuncControlTemplate<ListBoxItem>(parent => return new FuncControlTemplate<ListBoxItem>((parent, scope) =>
new ContentPresenter new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = parent[!ListBoxItem.ContentProperty], [!ContentPresenter.ContentProperty] = parent[!ListBoxItem.ContentProperty],
[!ContentPresenter.ContentTemplateProperty] = parent[!ListBoxItem.ContentTemplateProperty], [!ContentPresenter.ContentTemplateProperty] = parent[!ListBoxItem.ContentTemplateProperty],
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private FuncControlTemplate ScrollViewerTemplate() private FuncControlTemplate ScrollViewerTemplate()
{ {
return new FuncControlTemplate<ScrollViewer>(parent => return new FuncControlTemplate<ScrollViewer>((parent, scope) =>
new ScrollContentPresenter new ScrollContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
@ -370,7 +370,7 @@ namespace Avalonia.Controls.UnitTests
[~~ScrollContentPresenter.ExtentProperty] = parent[~~ScrollViewer.ExtentProperty], [~~ScrollContentPresenter.ExtentProperty] = parent[~~ScrollViewer.ExtentProperty],
[~~ScrollContentPresenter.OffsetProperty] = parent[~~ScrollViewer.OffsetProperty], [~~ScrollContentPresenter.OffsetProperty] = parent[~~ScrollViewer.OffsetProperty],
[~~ScrollContentPresenter.ViewportProperty] = parent[~~ScrollViewer.ViewportProperty], [~~ScrollContentPresenter.ViewportProperty] = parent[~~ScrollViewer.ViewportProperty],
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private void Prepare(ListBox target) private void Prepare(ListBox target)

13
tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs

@ -245,7 +245,7 @@ namespace Avalonia.Controls.UnitTests
} }
} }
private Control CreateListBoxTemplate(ITemplatedControl parent) private Control CreateListBoxTemplate(ITemplatedControl parent, INameScope scope)
{ {
return new ScrollViewer return new ScrollViewer
{ {
@ -254,17 +254,18 @@ namespace Avalonia.Controls.UnitTests
{ {
Name = "PART_ItemsPresenter", Name = "PART_ItemsPresenter",
[~ItemsPresenter.ItemsProperty] = parent.GetObservable(ItemsControl.ItemsProperty).ToBinding(), [~ItemsPresenter.ItemsProperty] = parent.GetObservable(ItemsControl.ItemsProperty).ToBinding(),
} }.RegisterInNameScope(scope)
}; }.WithNameScope(scope);
} }
private Control CreateScrollViewerTemplate(ITemplatedControl parent) private Control CreateScrollViewerTemplate(ITemplatedControl parent, INameScope scope)
{ {
return new ScrollContentPresenter return new ScrollContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[~ContentPresenter.ContentProperty] = parent.GetObservable(ContentControl.ContentProperty).ToBinding(), [~ContentPresenter.ContentProperty] =
}; parent.GetObservable(ContentControl.ContentProperty).ToBinding(),
}.RegisterInNameScope(scope).WithNameScope(scope);
} }
private void ApplyTemplate(ListBox target) private void ApplyTemplate(ListBox target)

17
tests/Avalonia.Controls.UnitTests/Mixins/ContentControlMixinTests.cs

@ -21,15 +21,16 @@ namespace Avalonia.Controls.UnitTests.Mixins
{ {
var target = new TestControl() var target = new TestControl()
{ {
Template = new FuncControlTemplate(_ => new Panel Template = new FuncControlTemplate((_, scope) => new Panel
{ {
Children = Children =
{ {
new ContentPresenter { Name = "Content_1_Presenter" }, new ContentPresenter {Name = "Content_1_Presenter"}.RegisterInNameScope(scope),
new ContentPresenter { Name = "Content_2_Presenter" } new ContentPresenter {Name = "Content_2_Presenter"}.RegisterInNameScope(scope)
} }
}) }.WithNameScope(scope))
}; };
var ex = Record.Exception(() => target.ApplyTemplate()); var ex = Record.Exception(() => target.ApplyTemplate());
@ -43,14 +44,14 @@ namespace Avalonia.Controls.UnitTests.Mixins
var p2 = new ContentPresenter { Name = "Content_2_Presenter" }; var p2 = new ContentPresenter { Name = "Content_2_Presenter" };
var target = new TestControl var target = new TestControl
{ {
Template = new FuncControlTemplate(_ => new Panel Template = new FuncControlTemplate((_, scope) => new Panel
{ {
Children = Children =
{ {
p1, p1.RegisterInNameScope(scope),
p2 p2.RegisterInNameScope(scope)
} }
}) }.WithNameScope(scope))
}; };
target.ApplyTemplate(); target.ApplyTemplate();

18
tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_InTemplate.cs

@ -170,7 +170,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
{ {
var (target, _) = CreateTarget(); var (target, _) = CreateTarget();
target.ContentTemplate = new FuncDataTemplate<string>(_ => new Canvas()); target.ContentTemplate = new FuncDataTemplate<string>((_, __) => new Canvas());
target.Content = "Foo"; target.Content = "Foo";
Assert.IsType<Canvas>(target.Child); Assert.IsType<Canvas>(target.Child);
@ -184,7 +184,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.Content = "Foo"; target.Content = "Foo";
Assert.IsType<TextBlock>(target.Child); Assert.IsType<TextBlock>(target.Child);
target.ContentTemplate = new FuncDataTemplate<string>(_ => new Canvas()); target.ContentTemplate = new FuncDataTemplate<string>((_, __) => new Canvas());
Assert.IsType<Canvas>(target.Child); Assert.IsType<Canvas>(target.Child);
target.ContentTemplate = null; target.ContentTemplate = null;
@ -209,7 +209,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
public void Recycles_DataTemplate() public void Recycles_DataTemplate()
{ {
var (target, _) = CreateTarget(); var (target, _) = CreateTarget();
target.DataTemplates.Add(new FuncDataTemplate<string>(_ => new Border(), true)); target.DataTemplates.Add(new FuncDataTemplate<string>((_, __) => new Border(), true));
target.Content = "foo"; target.Content = "foo";
@ -239,7 +239,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
public void Detects_DataTemplate_Doesnt_Support_Recycling() public void Detects_DataTemplate_Doesnt_Support_Recycling()
{ {
var (target, _) = CreateTarget(); var (target, _) = CreateTarget();
target.DataTemplates.Add(new FuncDataTemplate<string>(_ => new Border(), false)); target.DataTemplates.Add(new FuncDataTemplate<string>((_, __) => new Border(), false));
target.Content = "foo"; target.Content = "foo";
@ -256,7 +256,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
var (target, _) = CreateTarget(); var (target, _) = CreateTarget();
target.DataTemplates.Add(new FuncDataTemplate<string>(x => x == "bar", _ => new Canvas(), true)); target.DataTemplates.Add(new FuncDataTemplate<string>(x => x == "bar", _ => new Canvas(), true));
target.DataTemplates.Add(new FuncDataTemplate<string>(_ => new Border(), true)); target.DataTemplates.Add(new FuncDataTemplate<string>((_, __) => new Border(), true));
target.Content = "foo"; target.Content = "foo";
@ -278,8 +278,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
}; };
var (target, host) = CreateTarget(); var (target, host) = CreateTarget();
host.DataTemplates.Add(new FuncDataTemplate<string>(x => textBlock)); host.DataTemplates.Add(new FuncDataTemplate<string>((_, __) => textBlock));
host.DataTemplates.Add(new FuncDataTemplate<int>(x => new Canvas())); host.DataTemplates.Add(new FuncDataTemplate<int>((_, __) => new Canvas()));
target.Content = "foo"; target.Content = "foo";
Assert.Same(textBlock, target.Child); Assert.Same(textBlock, target.Child);
@ -296,11 +296,11 @@ namespace Avalonia.Controls.UnitTests.Presenters
{ {
var templatedParent = new ContentControl var templatedParent = new ContentControl
{ {
Template = new FuncControlTemplate<ContentControl>(x => Template = new FuncControlTemplate<ContentControl>((_, s) =>
new ContentPresenter new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
}), }.RegisterInNameScope(s).WithNameScope(s)),
}; };
var root = new TestRoot { Child = templatedParent }; var root = new TestRoot { Child = templatedParent };

16
tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Standalone.cs

@ -54,7 +54,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
var target = new ContentPresenter var target = new ContentPresenter
{ {
ContentTemplate = ContentTemplate =
new FuncDataTemplate<string>(t => new ContentControl() { Content = t }, false) new FuncDataTemplate<string>((t, _) => new ContentControl() { Content = t }, false)
}; };
var parentMock = new Mock<Control>(); var parentMock = new Mock<Control>();
@ -93,14 +93,14 @@ namespace Avalonia.Controls.UnitTests.Presenters
{ {
var contentControl = new ContentControl var contentControl = new ContentControl
{ {
Template = new FuncControlTemplate<ContentControl>(c => new ContentPresenter() Template = new FuncControlTemplate<ContentControl>((c, scope) => new ContentPresenter()
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[~ContentPresenter.ContentProperty] = c[~ContentControl.ContentProperty], [~ContentPresenter.ContentProperty] = c[~ContentControl.ContentProperty],
[~ContentPresenter.ContentTemplateProperty] = c[~ContentControl.ContentTemplateProperty] [~ContentPresenter.ContentTemplateProperty] = c[~ContentControl.ContentTemplateProperty]
}), }.RegisterInNameScope(scope).WithNameScope(scope)),
ContentTemplate = ContentTemplate =
new FuncDataTemplate<string>(t => new ContentControl() { Content = t }, false) new FuncDataTemplate<string>((t, _) => new ContentControl() { Content = t }, false)
}; };
var parentMock = new Mock<Control>(); var parentMock = new Mock<Control>();
@ -144,7 +144,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
var target = new ContentPresenter var target = new ContentPresenter
{ {
ContentTemplate = ContentTemplate =
new FuncDataTemplate<string>(t => new ContentControl() { Content = t }, false) new FuncDataTemplate<string>((t, _) => new ContentControl() { Content = t }, false)
}; };
var parentMock = new Mock<Control>(); var parentMock = new Mock<Control>();
@ -179,7 +179,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
var target = new ContentPresenter var target = new ContentPresenter
{ {
ContentTemplate = ContentTemplate =
new FuncDataTemplate<string>(t => new ContentControl() { Content = t }, false) new FuncDataTemplate<string>((t, _) => new ContentControl() { Content = t }, false)
}; };
target.Content = "foo"; target.Content = "foo";
@ -235,8 +235,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
{ {
DataTemplates = DataTemplates =
{ {
new FuncDataTemplate<string>(x => textBlock), new FuncDataTemplate<string>((x, _) => textBlock),
new FuncDataTemplate<int>(x => new Canvas()), new FuncDataTemplate<int>((x, _) => new Canvas()),
}, },
}; };

4
tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Unrooted.cs

@ -90,7 +90,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
{ {
DataTemplates = DataTemplates =
{ {
new FuncDataTemplate<string>(x => new Decorator()), new FuncDataTemplate<string>((x, _) => new Decorator()),
}, },
}; };
@ -99,4 +99,4 @@ namespace Avalonia.Controls.UnitTests.Presenters
Assert.IsType<Decorator>(target.Child); Assert.IsType<Decorator>(target.Child);
} }
} }
} }

2
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs

@ -220,7 +220,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
{ {
VirtualizationMode = ItemVirtualizationMode.None, VirtualizationMode = ItemVirtualizationMode.None,
Items = items, Items = items,
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Height = 10 }), ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Height = 10 }),
}; };
target.ApplyTemplate(); target.ApplyTemplate();

2
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs

@ -309,7 +309,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
private static IDataTemplate ItemTemplate() private static IDataTemplate ItemTemplate()
{ {
return new FuncDataTemplate<string>(x => new Canvas return new FuncDataTemplate<string>((x, _) => new Canvas
{ {
Width = 10, Width = 10,
Height = 10, Height = 10,

8
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs

@ -470,7 +470,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
{ {
VirtualizationMode = ItemVirtualizationMode.None, VirtualizationMode = ItemVirtualizationMode.None,
Items = items, Items = items,
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Height = 10 }), ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Height = 10 }),
}; };
target.ApplyTemplate(); target.ApplyTemplate();
@ -1046,7 +1046,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
private static IDataTemplate StringDataTemplate() private static IDataTemplate StringDataTemplate()
{ {
return new FuncDataTemplate<string>(x => new Canvas return new FuncDataTemplate<string>((x, _) => new Canvas
{ {
Width = 10, Width = 10,
Height = 10, Height = 10,
@ -1095,12 +1095,12 @@ namespace Avalonia.Controls.UnitTests.Presenters
{ {
public TestContainer() public TestContainer()
{ {
Template = new FuncControlTemplate<TestContainer>(parent => new ContentPresenter Template = new FuncControlTemplate<TestContainer>((parent, scope) => new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty], [~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty],
[~ContentPresenter.ContentTemplateProperty] = parent[~ContentControl.ContentTemplateProperty], [~ContentPresenter.ContentTemplateProperty] = parent[~ContentControl.ContentTemplateProperty],
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
} }
} }

6
tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs

@ -134,12 +134,12 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
var result = new PopupRoot var result = new PopupRoot
{ {
Template = new FuncControlTemplate<PopupRoot>(parent => Template = new FuncControlTemplate<PopupRoot>((parent, scope) =>
new ContentPresenter new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = parent[!PopupRoot.ContentProperty], [!ContentPresenter.ContentProperty] = parent[!PopupRoot.ContentProperty],
}), }.RegisterInNameScope(scope).WithNameScope(scope)),
}; };
result.ApplyTemplate(); result.ApplyTemplate();
@ -154,7 +154,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
public TemplatedControlWithPopup() public TemplatedControlWithPopup()
{ {
Template = new FuncControlTemplate<TemplatedControlWithPopup>(parent => Template = new FuncControlTemplate<TemplatedControlWithPopup>((parent, _) =>
new Popup new Popup
{ {
[!Popup.ChildProperty] = parent[!TemplatedControlWithPopup.PopupContentProperty], [!Popup.ChildProperty] = parent[!TemplatedControlWithPopup.PopupContentProperty],

8
tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs

@ -315,16 +315,16 @@ namespace Avalonia.Controls.UnitTests.Primitives
return result; return result;
} }
private static IControl PopupRootTemplate(PopupRoot control) private static IControl PopupRootTemplate(PopupRoot control, INameScope scope)
{ {
return new ContentPresenter return new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[~ContentPresenter.ContentProperty] = control[~ContentControl.ContentProperty], [~ContentPresenter.ContentProperty] = control[~ContentControl.ContentProperty],
}; }.RegisterInNameScope(scope).WithNameScope(scope);
} }
private static IControl PopupContentControlTemplate(PopupContentControl control) private static IControl PopupContentControlTemplate(PopupContentControl control, INameScope scope)
{ {
return new Popup return new Popup
{ {
@ -333,7 +333,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
[~ContentPresenter.ContentProperty] = control[~ContentControl.ContentProperty], [~ContentPresenter.ContentProperty] = control[~ContentControl.ContentProperty],
} }
}; }.RegisterInNameScope(scope).WithNameScope(scope);
} }
private class PopupContentControl : ContentControl private class PopupContentControl : ContentControl

6
tests/Avalonia.Controls.UnitTests/Primitives/RangeBaseTests.cs

@ -111,7 +111,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
var target = new TestRange() var target = new TestRange()
{ {
Template = new FuncControlTemplate<RangeBase>(c => Template = new FuncControlTemplate<RangeBase>((c, scope) =>
{ {
track = new Track() track = new Track()
{ {
@ -122,7 +122,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
Name = "PART_Track", Name = "PART_Track",
Thumb = new Thumb() Thumb = new Thumb()
}; }.RegisterInNameScope(scope);
if (useXamlBinding) if (useXamlBinding)
{ {
@ -138,7 +138,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
track[~~Track.ValueProperty] = c[~~RangeBase.ValueProperty]; track[~~Track.ValueProperty] = c[~~RangeBase.ValueProperty];
} }
return track; return track.WithNameScope(scope);
}), }),
Minimum = 0, Minimum = 0,
Maximum = 100, Maximum = 100,

10
tests/Avalonia.Controls.UnitTests/Primitives/ScrollBarTests.cs

@ -169,7 +169,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
Assert.False(target.IsVisible); Assert.False(target.IsVisible);
} }
private static Control Template(ScrollBar control) private static Control Template(ScrollBar control, INameScope scope)
{ {
return new Border return new Border
{ {
@ -185,11 +185,11 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
Template = new FuncControlTemplate<Thumb>(ThumbTemplate), Template = new FuncControlTemplate<Thumb>(ThumbTemplate),
}, },
}, }.RegisterInNameScope(scope),
}; }.WithNameScope(scope);
} }
private static Control ThumbTemplate(Thumb control) private static Control ThumbTemplate(Thumb control, INameScope scope)
{ {
return new Border return new Border
{ {
@ -197,4 +197,4 @@ namespace Avalonia.Controls.UnitTests.Primitives
}; };
} }
} }
} }

4
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs

@ -896,13 +896,13 @@ namespace Avalonia.Controls.UnitTests.Primitives
private FuncControlTemplate Template() private FuncControlTemplate Template()
{ {
return new FuncControlTemplate<SelectingItemsControl>(control => return new FuncControlTemplate<SelectingItemsControl>((control, scope) =>
new ItemsPresenter new ItemsPresenter
{ {
Name = "itemsPresenter", Name = "itemsPresenter",
[~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty], [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
[~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty], [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private class Item : Control, ISelectable private class Item : Control, ISelectable

4
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs

@ -84,13 +84,13 @@ namespace Avalonia.Controls.UnitTests.Primitives
private FuncControlTemplate Template() private FuncControlTemplate Template()
{ {
return new FuncControlTemplate<SelectingItemsControl>(control => return new FuncControlTemplate<SelectingItemsControl>((control, scope) =>
new ItemsPresenter new ItemsPresenter
{ {
Name = "itemsPresenter", Name = "itemsPresenter",
[~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty], [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
[~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty], [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private class TestSelector : SelectingItemsControl private class TestSelector : SelectingItemsControl

10
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs

@ -964,7 +964,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
Template = Template(), Template = Template(),
Items = new[] { "Foo", "Bar", "Baz" }, Items = new[] { "Foo", "Bar", "Baz" },
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Width = 20, Height = 10 }), ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
SelectionMode = SelectionMode.Multiple, SelectionMode = SelectionMode.Multiple,
}; };
@ -988,7 +988,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
Template = Template(), Template = Template(),
Items = new[] { "Foo", "Bar", "Baz" }, Items = new[] { "Foo", "Bar", "Baz" },
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Width = 20, Height = 10 }), ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
SelectionMode = SelectionMode.Multiple, SelectionMode = SelectionMode.Multiple,
}; };
@ -1010,7 +1010,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
Template = Template(), Template = Template(),
Items = new[] { "Foo", "Bar", "Baz" }, Items = new[] { "Foo", "Bar", "Baz" },
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Width = 20, Height = 10 }), ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
SelectionMode = SelectionMode.Multiple, SelectionMode = SelectionMode.Multiple,
}; };
@ -1035,13 +1035,13 @@ namespace Avalonia.Controls.UnitTests.Primitives
private FuncControlTemplate Template() private FuncControlTemplate Template()
{ {
return new FuncControlTemplate<SelectingItemsControl>(control => return new FuncControlTemplate<SelectingItemsControl>((control, scope) =>
new ItemsPresenter new ItemsPresenter
{ {
Name = "PART_ItemsPresenter", Name = "PART_ItemsPresenter",
[~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty], [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
[~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty], [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private class TestSelector : SelectingItemsControl private class TestSelector : SelectingItemsControl

4
tests/Avalonia.Controls.UnitTests/Primitives/TabStripTests.cs

@ -159,14 +159,14 @@ namespace Avalonia.Controls.UnitTests.Primitives
Assert.Same("3rd", ((TabItem)target.SelectedItem).Name); Assert.Same("3rd", ((TabItem)target.SelectedItem).Name);
} }
private Control CreateTabStripTemplate(TabStrip parent) private Control CreateTabStripTemplate(TabStrip parent, INameScope scope)
{ {
return new ItemsPresenter return new ItemsPresenter
{ {
Name = "itemsPresenter", Name = "itemsPresenter",
[!ItemsPresenter.ItemsProperty] = parent[!ItemsControl.ItemsProperty], [!ItemsPresenter.ItemsProperty] = parent[!ItemsControl.ItemsProperty],
[!ItemsPresenter.MemberSelectorProperty] = parent[!ItemsControl.MemberSelectorProperty], [!ItemsPresenter.MemberSelectorProperty] = parent[!ItemsControl.MemberSelectorProperty],
}; }.RegisterInNameScope(scope).WithNameScope(scope);
} }
} }
} }

58
tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs

@ -23,7 +23,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
bool executed = false; bool executed = false;
var template = new FuncControlTemplate(_ => var template = new FuncControlTemplate((_, __) =>
{ {
executed = true; executed = true;
return new Control(); return new Control();
@ -42,7 +42,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
bool executed = false; bool executed = false;
var template = new FuncControlTemplate(_ => var template = new FuncControlTemplate((_, __) =>
{ {
executed = true; executed = true;
return new Control(); return new Control();
@ -63,7 +63,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
var target = new TemplatedControl var target = new TemplatedControl
{ {
Template = new FuncControlTemplate(_ => new Decorator Template = new FuncControlTemplate((_, __) => new Decorator
{ {
Child = new Panel Child = new Panel
{ {
@ -97,7 +97,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
var target = new TemplatedControl var target = new TemplatedControl
{ {
Template = new FuncControlTemplate(_ => new Decorator Template = new FuncControlTemplate((_, __) => new Decorator
{ {
Child = new Panel Child = new Panel
{ {
@ -120,7 +120,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
var target = new TemplatedControl var target = new TemplatedControl
{ {
Template = new FuncControlTemplate(_ => new Decorator Template = new FuncControlTemplate((_, __) => new Decorator
{ {
Child = new Panel Child = new Panel
{ {
@ -149,7 +149,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
var target = new TemplatedControl var target = new TemplatedControl
{ {
Template = new FuncControlTemplate(_ => new Decorator()) Template = new FuncControlTemplate((_, __) => new Decorator())
}; };
target.ApplyTemplate(); target.ApplyTemplate();
@ -165,14 +165,14 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
var target = new TemplatedControl var target = new TemplatedControl
{ {
Template = new FuncControlTemplate(_ => new Decorator()) Template = new FuncControlTemplate((_, __) => new Decorator())
}; };
target.ApplyTemplate(); target.ApplyTemplate();
var child = (Decorator)target.GetVisualChildren().Single(); var child = (Decorator)target.GetVisualChildren().Single();
target.Template = new FuncControlTemplate(_ => new Canvas()); target.Template = new FuncControlTemplate((_, __) => new Canvas());
target.ApplyTemplate(); target.ApplyTemplate();
Assert.Null(child.Parent); Assert.Null(child.Parent);
@ -183,7 +183,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
var target = new TemplatedControl var target = new TemplatedControl
{ {
Template = new FuncControlTemplate(_ => new ScrollViewer()) Template = new FuncControlTemplate((_, __) => new ScrollViewer())
}; };
target.ApplyTemplate(); target.ApplyTemplate();
@ -203,7 +203,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
Child = target = new TestTemplatedControl Child = target = new TestTemplatedControl
{ {
Template = new FuncControlTemplate(_ => Template = new FuncControlTemplate((_, __) =>
{ {
return new StackPanel return new StackPanel
{ {
@ -232,11 +232,11 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
var target = new TestTemplatedControl var target = new TestTemplatedControl
{ {
Template = new FuncControlTemplate(_ => Template = new FuncControlTemplate((_, __) =>
{ {
return new ContentControl return new ContentControl
{ {
Template = new FuncControlTemplate(parent => Template = new FuncControlTemplate((parent, ___) =>
{ {
return new Border return new Border
{ {
@ -311,7 +311,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
var target = new TestTemplatedControl var target = new TestTemplatedControl
{ {
Template = new FuncControlTemplate(_ => new Decorator()) Template = new FuncControlTemplate((_, __) => new Decorator())
}; };
var raised = false; var raised = false;
@ -334,7 +334,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
var target = new TestTemplatedControl var target = new TestTemplatedControl
{ {
Template = new FuncControlTemplate(_ => new Decorator Template = new FuncControlTemplate((_, __) => new Decorator
{ {
Child = new Border(), Child = new Border(),
}) })
@ -348,7 +348,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
Assert.Equal(target, decorator.TemplatedParent); Assert.Equal(target, decorator.TemplatedParent);
Assert.Equal(target, border.TemplatedParent); Assert.Equal(target, border.TemplatedParent);
target.Template = new FuncControlTemplate(_ => new Canvas()); target.Template = new FuncControlTemplate((_, __) => new Canvas());
// Templated children should not be removed here: the control may be re-added // Templated children should not be removed here: the control may be re-added
// somewhere with the same template, so they could still be of use. // somewhere with the same template, so they could still be of use.
@ -370,7 +370,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
Child = new TestTemplatedControl Child = new TestTemplatedControl
{ {
Template = new FuncControlTemplate(_ => new Decorator Template = new FuncControlTemplate((_, __) => new Decorator
{ {
Child = templateChild, Child = templateChild,
}) })
@ -392,7 +392,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
Child = new TestTemplatedControl Child = new TestTemplatedControl
{ {
Template = new FuncControlTemplate(_ => new Decorator Template = new FuncControlTemplate((_, __) => new Decorator
{ {
Child = templateChild, Child = templateChild,
}) })
@ -425,7 +425,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
new Setter( new Setter(
TemplatedControl.TemplateProperty, TemplatedControl.TemplateProperty,
new FuncControlTemplate(_ => new Decorator new FuncControlTemplate((_, __) => new Decorator
{ {
Child = new Border(), Child = new Border(),
})) }))
@ -461,7 +461,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
new Setter( new Setter(
TemplatedControl.TemplateProperty, TemplatedControl.TemplateProperty,
new FuncControlTemplate(_ => new Decorator new FuncControlTemplate((_, __) => new Decorator
{ {
Child = new Border(), Child = new Border(),
})) }))
@ -500,7 +500,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
new Setter( new Setter(
TemplatedControl.TemplateProperty, TemplatedControl.TemplateProperty,
new FuncControlTemplate(_ => new Decorator new FuncControlTemplate((_, __) => new Decorator
{ {
Child = new Border(), Child = new Border(),
})) }))
@ -520,7 +520,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
new Setter( new Setter(
TemplatedControl.TemplateProperty, TemplatedControl.TemplateProperty,
new FuncControlTemplate(_ => new Decorator new FuncControlTemplate((_, __) => new Decorator
{ {
Child = new Border(), Child = new Border(),
})) }))
@ -555,7 +555,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
Child = target = new TestTemplatedControl Child = target = new TestTemplatedControl
{ {
Template = new FuncControlTemplate(_ => new Decorator()), Template = new FuncControlTemplate((_, __) => new Decorator()),
} }
}; };
@ -573,7 +573,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
} }
} }
private static IControl ScrollingContentControlTemplate(ContentControl control) private static IControl ScrollingContentControlTemplate(ContentControl control, INameScope scope)
{ {
return new Border return new Border
{ {
@ -585,20 +585,20 @@ namespace Avalonia.Controls.UnitTests.Primitives
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = control[!ContentControl.ContentProperty], [!ContentPresenter.ContentProperty] = control[!ContentControl.ContentProperty],
} }.RegisterInNameScope(scope)
} }.RegisterInNameScope(scope)
}; }.WithNameScope(scope);
} }
private static Control ScrollViewerTemplate(ScrollViewer control) private static Control ScrollViewerTemplate(ScrollViewer control, INameScope scope)
{ {
var result = new ScrollContentPresenter var result = new ScrollContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[~ContentPresenter.ContentProperty] = control[~ContentControl.ContentProperty], [~ContentPresenter.ContentProperty] = control[~ContentControl.ContentProperty],
}; }.RegisterInNameScope(scope).WithNameScope(scope);
return result; return result;
} }
} }
} }

12
tests/Avalonia.Controls.UnitTests/ScrollViewerTests.cs

@ -64,7 +64,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new Vector(10, 10), target.Offset); Assert.Equal(new Vector(10, 10), target.Offset);
} }
private Control CreateTemplate(ScrollViewer control) private Control CreateTemplate(ScrollViewer control, INameScope scope)
{ {
return new Grid return new Grid
{ {
@ -88,7 +88,7 @@ namespace Avalonia.Controls.UnitTests
[~~ScrollContentPresenter.OffsetProperty] = control[~~ScrollViewer.OffsetProperty], [~~ScrollContentPresenter.OffsetProperty] = control[~~ScrollViewer.OffsetProperty],
[~~ScrollContentPresenter.ViewportProperty] = control[~~ScrollViewer.ViewportProperty], [~~ScrollContentPresenter.ViewportProperty] = control[~~ScrollViewer.ViewportProperty],
[~ScrollContentPresenter.CanHorizontallyScrollProperty] = control[~ScrollViewer.CanHorizontallyScrollProperty], [~ScrollContentPresenter.CanHorizontallyScrollProperty] = control[~ScrollViewer.CanHorizontallyScrollProperty],
}, }.RegisterInNameScope(scope),
new ScrollBar new ScrollBar
{ {
Name = "horizontalScrollBar", Name = "horizontalScrollBar",
@ -98,7 +98,7 @@ namespace Avalonia.Controls.UnitTests
[~ScrollBar.ViewportSizeProperty] = control[~ScrollViewer.HorizontalScrollBarViewportSizeProperty], [~ScrollBar.ViewportSizeProperty] = control[~ScrollViewer.HorizontalScrollBarViewportSizeProperty],
[~ScrollBar.VisibilityProperty] = control[~ScrollViewer.HorizontalScrollBarVisibilityProperty], [~ScrollBar.VisibilityProperty] = control[~ScrollViewer.HorizontalScrollBarVisibilityProperty],
[Grid.RowProperty] = 1, [Grid.RowProperty] = 1,
}, }.RegisterInNameScope(scope),
new ScrollBar new ScrollBar
{ {
Name = "verticalScrollBar", Name = "verticalScrollBar",
@ -108,9 +108,9 @@ namespace Avalonia.Controls.UnitTests
[~ScrollBar.ViewportSizeProperty] = control[~ScrollViewer.VerticalScrollBarViewportSizeProperty], [~ScrollBar.ViewportSizeProperty] = control[~ScrollViewer.VerticalScrollBarViewportSizeProperty],
[~ScrollBar.VisibilityProperty] = control[~ScrollViewer.VerticalScrollBarVisibilityProperty], [~ScrollBar.VisibilityProperty] = control[~ScrollViewer.VerticalScrollBarVisibilityProperty],
[Grid.ColumnProperty] = 1, [Grid.ColumnProperty] = 1,
}, }.RegisterInNameScope(scope),
}, },
}; }.WithNameScope(scope);
} }
} }
} }

18
tests/Avalonia.Controls.UnitTests/TabControlTests.cs

@ -129,7 +129,7 @@ namespace Avalonia.Controls.UnitTests
}, },
}; };
var template = new FuncControlTemplate<TabItem>(x => new Decorator()); var template = new FuncControlTemplate<TabItem>((x, __) => new Decorator());
using (UnitTestApplication.Start(TestServices.RealStyler)) using (UnitTestApplication.Start(TestServices.RealStyler))
{ {
@ -176,7 +176,7 @@ namespace Avalonia.Controls.UnitTests
DataContext = "Base", DataContext = "Base",
DataTemplates = DataTemplates =
{ {
new FuncDataTemplate<Item>(x => new Button { Content = x }) new FuncDataTemplate<Item>((x, __) => new Button { Content = x })
}, },
Items = items, Items = items,
}; };
@ -273,7 +273,7 @@ namespace Avalonia.Controls.UnitTests
TabControl target = new TabControl TabControl target = new TabControl
{ {
Template = TabControlTemplate(), Template = TabControlTemplate(),
ContentTemplate = new FuncDataTemplate<string>(x => ContentTemplate = new FuncDataTemplate<string>((x, _) =>
new TextBlock { Tag = "bar", Text = x }), new TextBlock { Tag = "bar", Text = x }),
Items = new[] { "Foo" }, Items = new[] { "Foo" },
}; };
@ -289,7 +289,7 @@ namespace Avalonia.Controls.UnitTests
private IControlTemplate TabControlTemplate() private IControlTemplate TabControlTemplate()
{ {
return new FuncControlTemplate<TabControl>(parent => return new FuncControlTemplate<TabControl>((parent, scope) =>
new StackPanel new StackPanel
{ {
Children = Children =
@ -299,26 +299,26 @@ namespace Avalonia.Controls.UnitTests
Name = "PART_ItemsPresenter", Name = "PART_ItemsPresenter",
[!TabStrip.ItemsProperty] = parent[!TabControl.ItemsProperty], [!TabStrip.ItemsProperty] = parent[!TabControl.ItemsProperty],
[!TabStrip.ItemTemplateProperty] = parent[!TabControl.ItemTemplateProperty], [!TabStrip.ItemTemplateProperty] = parent[!TabControl.ItemTemplateProperty],
}, }.RegisterInNameScope(scope),
new ContentPresenter new ContentPresenter
{ {
Name = "PART_SelectedContentHost", Name = "PART_SelectedContentHost",
[!ContentPresenter.ContentProperty] = parent[!TabControl.SelectedContentProperty], [!ContentPresenter.ContentProperty] = parent[!TabControl.SelectedContentProperty],
[!ContentPresenter.ContentTemplateProperty] = parent[!TabControl.SelectedContentTemplateProperty], [!ContentPresenter.ContentTemplateProperty] = parent[!TabControl.SelectedContentTemplateProperty],
} }.RegisterInNameScope(scope)
} }
}); }.WithNameScope(scope));
} }
private IControlTemplate TabItemTemplate() private IControlTemplate TabItemTemplate()
{ {
return new FuncControlTemplate<TabItem>(parent => return new FuncControlTemplate<TabItem>((parent, scope) =>
new ContentPresenter new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = parent[!TabItem.HeaderProperty], [!ContentPresenter.ContentProperty] = parent[!TabItem.HeaderProperty],
[!ContentPresenter.ContentTemplateProperty] = parent[!TabItem.HeaderTemplateProperty] [!ContentPresenter.ContentTemplateProperty] = parent[!TabItem.HeaderTemplateProperty]
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private void ApplyTemplate(TabControl target) private void ApplyTemplate(TabControl target)

4
tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

@ -456,7 +456,7 @@ namespace Avalonia.Controls.UnitTests
private IControlTemplate CreateTemplate() private IControlTemplate CreateTemplate()
{ {
return new FuncControlTemplate<TextBox>(control => return new FuncControlTemplate<TextBox>((control, scope) =>
new TextPresenter new TextPresenter
{ {
Name = "PART_TextPresenter", Name = "PART_TextPresenter",
@ -467,7 +467,7 @@ namespace Avalonia.Controls.UnitTests
Priority = BindingPriority.TemplatedParent, Priority = BindingPriority.TemplatedParent,
RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent), RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
}, },
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private void RaiseKeyEvent(TextBox textBox, Key key, InputModifiers inputModifiers) private void RaiseKeyEvent(TextBox textBox, Key key, InputModifiers inputModifiers)

4
tests/Avalonia.Controls.UnitTests/TextBoxTests_DataValidation.cs

@ -93,7 +93,7 @@ namespace Avalonia.Controls.UnitTests
private IControlTemplate CreateTemplate() private IControlTemplate CreateTemplate()
{ {
return new FuncControlTemplate<TextBox>(control => return new FuncControlTemplate<TextBox>((control, scope) =>
new TextPresenter new TextPresenter
{ {
Name = "PART_TextPresenter", Name = "PART_TextPresenter",
@ -104,7 +104,7 @@ namespace Avalonia.Controls.UnitTests
Priority = BindingPriority.TemplatedParent, Priority = BindingPriority.TemplatedParent,
RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent), RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
}, },
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private class ExceptionTest private class ExceptionTest

4
tests/Avalonia.Controls.UnitTests/TopLevelTests.cs

@ -226,12 +226,12 @@ namespace Avalonia.Controls.UnitTests
private FuncControlTemplate<TestTopLevel> CreateTemplate() private FuncControlTemplate<TestTopLevel> CreateTemplate()
{ {
return new FuncControlTemplate<TestTopLevel>(x => return new FuncControlTemplate<TestTopLevel>((x, scope) =>
new ContentPresenter new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = x[!ContentControl.ContentProperty], [!ContentPresenter.ContentProperty] = x[!ContentControl.ContentProperty],
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private class TestTopLevel : TopLevel private class TestTopLevel : TopLevel

18
tests/Avalonia.Controls.UnitTests/TreeViewTests.cs

@ -50,7 +50,7 @@ namespace Avalonia.Controls.UnitTests
Template = CreateTreeViewTemplate(), Template = CreateTreeViewTemplate(),
Items = CreateTestTreeData(), Items = CreateTestTreeData(),
ItemTemplate = new FuncTreeDataTemplate<Node>( ItemTemplate = new FuncTreeDataTemplate<Node>(
_ => new Canvas(), (_, __) => new Canvas(),
x => x.Children), x => x.Children),
} }
}; };
@ -475,7 +475,7 @@ namespace Avalonia.Controls.UnitTests
DataContext = "Base", DataContext = "Base",
DataTemplates = DataTemplates =
{ {
new FuncDataTemplate<Node>(x => new Button { Content = x }) new FuncDataTemplate<Node>((x, _) => new Button { Content = x })
}, },
Items = items, Items = items,
}; };
@ -513,7 +513,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Null(NameScope.GetNameScope((TreeViewItem)item)); Assert.Null(NameScope.GetNameScope((TreeViewItem)item));
} }
[Fact] [Fact(Skip = "Is this behavior needed anymore?")]
public void DataTemplate_Created_Item_Should_Be_NameScope() public void DataTemplate_Created_Item_Should_Be_NameScope()
{ {
var items = new object[] var items = new object[]
@ -799,16 +799,16 @@ namespace Avalonia.Controls.UnitTests
private IControlTemplate CreateTreeViewTemplate() private IControlTemplate CreateTreeViewTemplate()
{ {
return new FuncControlTemplate<TreeView>(parent => new ItemsPresenter return new FuncControlTemplate<TreeView>((parent, scope) => new ItemsPresenter
{ {
Name = "PART_ItemsPresenter", Name = "PART_ItemsPresenter",
[~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty], [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private IControlTemplate CreateTreeViewItemTemplate() private IControlTemplate CreateTreeViewItemTemplate()
{ {
return new FuncControlTemplate<TreeViewItem>(parent => new Panel return new FuncControlTemplate<TreeViewItem>((parent, scope) => new Panel
{ {
Children = Children =
{ {
@ -816,14 +816,14 @@ namespace Avalonia.Controls.UnitTests
{ {
Name = "PART_HeaderPresenter", Name = "PART_HeaderPresenter",
[~ContentPresenter.ContentProperty] = parent[~TreeViewItem.HeaderProperty], [~ContentPresenter.ContentProperty] = parent[~TreeViewItem.HeaderProperty],
}, }.RegisterInNameScope(scope),
new ItemsPresenter new ItemsPresenter
{ {
Name = "PART_ItemsPresenter", Name = "PART_ItemsPresenter",
[~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty], [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
} }.RegisterInNameScope(scope)
} }
}); }.WithNameScope(scope));
} }
private List<string> ExtractItemHeader(TreeView tree, int level) private List<string> ExtractItemHeader(TreeView tree, int level)

6
tests/Avalonia.Controls.UnitTests/UserControlTests.cs

@ -40,7 +40,7 @@ namespace Avalonia.Controls.UnitTests
private FuncControlTemplate GetTemplate() private FuncControlTemplate GetTemplate()
{ {
return new FuncControlTemplate<UserControl>(parent => return new FuncControlTemplate<UserControl>((parent, scope) =>
{ {
return new Border return new Border
{ {
@ -49,8 +49,8 @@ namespace Avalonia.Controls.UnitTests
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty], [~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty],
} }.RegisterInNameScope(scope)
}; }.WithNameScope(scope);
}); });
} }
} }

4
tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs

@ -59,13 +59,13 @@ namespace Avalonia.Controls.UnitTests.Utils
private FuncControlTemplate CreateWindowTemplate() private FuncControlTemplate CreateWindowTemplate()
{ {
return new FuncControlTemplate<Window>(parent => return new FuncControlTemplate<Window>((parent, scope) =>
{ {
return new ContentPresenter return new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty], [~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty],
}; }.RegisterInNameScope(scope).WithNameScope(scope);
}); });
} }
} }

4
tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs

@ -253,12 +253,12 @@ namespace Avalonia.Controls.UnitTests
private FuncControlTemplate<TestWindowBase> CreateTemplate() private FuncControlTemplate<TestWindowBase> CreateTemplate()
{ {
return new FuncControlTemplate<TestWindowBase>(x => return new FuncControlTemplate<TestWindowBase>((x, scope) =>
new ContentPresenter new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = x[!ContentControl.ContentProperty], [!ContentPresenter.ContentProperty] = x[!ContentControl.ContentProperty],
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
private class TestWindowBase : WindowBase private class TestWindowBase : WindowBase

10
tests/Avalonia.Markup.UnitTests/Data/BindingTests_ElementName.cs

@ -34,6 +34,8 @@ namespace Avalonia.Markup.UnitTests.Data
} }
}; };
root.RegisterChildrenNames();
var binding = new Binding var binding = new Binding
{ {
ElementName = "source", ElementName = "source",
@ -69,6 +71,7 @@ namespace Avalonia.Markup.UnitTests.Data
} }
} }
}; };
root.RegisterChildrenNames();
var binding = new Binding var binding = new Binding
{ {
@ -99,7 +102,8 @@ namespace Avalonia.Markup.UnitTests.Data
} }
} }
}; };
root.RegisterChildrenNames();
var binding = new Binding var binding = new Binding
{ {
ElementName = "source", ElementName = "source",
@ -113,7 +117,7 @@ namespace Avalonia.Markup.UnitTests.Data
Name = "source", Name = "source",
Text = "foo", Text = "foo",
}); });
root.RegisterChildrenNames();
Assert.Equal("foo", target.Text); Assert.Equal("foo", target.Text);
} }
@ -136,6 +140,7 @@ namespace Avalonia.Markup.UnitTests.Data
} }
} }
}; };
root.RegisterChildrenNames();
var binding = new Binding var binding = new Binding
{ {
@ -151,6 +156,7 @@ namespace Avalonia.Markup.UnitTests.Data
}; };
stackPanel.Children.Add(source); stackPanel.Children.Add(source);
root.RegisterChildrenNames();
Assert.Same(source, target.Content); Assert.Same(source, target.Content);
} }

5
tests/Avalonia.Markup.UnitTests/Data/MultiBindingTests_Converters.cs

@ -23,9 +23,10 @@ namespace Avalonia.Markup.UnitTests.Data
DataContext = new Class1(), DataContext = new Class1(),
}; };
var format = "{0:0.0} + {1:00}";
var target = new MultiBinding var target = new MultiBinding
{ {
StringFormat = "{0:0.0} + {1:00}", StringFormat = format,
Bindings = Bindings =
{ {
new Binding(nameof(Class1.Foo)), new Binding(nameof(Class1.Foo)),
@ -35,7 +36,7 @@ namespace Avalonia.Markup.UnitTests.Data
textBlock.Bind(TextBlock.TextProperty, target); textBlock.Bind(TextBlock.TextProperty, target);
Assert.Equal("1.0 + 02", textBlock.Text); Assert.Equal(string.Format(format, 1, 2), textBlock.Text);
} }
[Fact] [Fact]

6
tests/Avalonia.Markup.UnitTests/Data/TemplateBindingTests.cs

@ -18,7 +18,7 @@ namespace Avalonia.Markup.UnitTests.Data
{ {
var source = new Button var source = new Button
{ {
Template = new FuncControlTemplate<Button>(parent => Template = new FuncControlTemplate<Button>((parent, _) =>
new ContentPresenter new ContentPresenter
{ {
[~ContentPresenter.ContentProperty] = new TemplateBinding(ContentControl.ContentProperty) [~ContentPresenter.ContentProperty] = new TemplateBinding(ContentControl.ContentProperty)
@ -41,7 +41,7 @@ namespace Avalonia.Markup.UnitTests.Data
{ {
var source = new Button var source = new Button
{ {
Template = new FuncControlTemplate<Button>(parent => Template = new FuncControlTemplate<Button>((parent, _) =>
new ContentPresenter new ContentPresenter
{ {
[~ContentPresenter.ContentProperty] = new TemplateBinding(ContentControl.ContentProperty) [~ContentPresenter.ContentProperty] = new TemplateBinding(ContentControl.ContentProperty)
@ -67,7 +67,7 @@ namespace Avalonia.Markup.UnitTests.Data
{ {
var source = new Button var source = new Button
{ {
Template = new FuncControlTemplate<Button>(parent => Template = new FuncControlTemplate<Button>((parent, _) =>
new ContentPresenter new ContentPresenter
{ {
[~ContentPresenter.ContentProperty] = new TemplateBinding(ContentControl.ContentProperty) [~ContentPresenter.ContentProperty] = new TemplateBinding(ContentControl.ContentProperty)

4
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/BindingExtensionTests.cs

@ -58,12 +58,12 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
{ {
new Setter( new Setter(
Window.TemplateProperty, Window.TemplateProperty,
new FuncControlTemplate<Window>(x => new FuncControlTemplate<Window>((x, scope) =>
new ContentPresenter new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = x[!Window.ContentProperty], [!ContentPresenter.ContentProperty] = x[!Window.ContentProperty],
})) }.RegisterInNameScope(scope).WithNameScope(scope)))
} }
}; };
} }

4
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs

@ -647,12 +647,12 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
{ {
new Setter( new Setter(
Window.TemplateProperty, Window.TemplateProperty,
new FuncControlTemplate<Window>(x => new FuncControlTemplate<Window>((x, scope) =>
new ContentPresenter new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = x[!Window.ContentProperty], [!ContentPresenter.ContentProperty] = x[!Window.ContentProperty],
})) }.RegisterInNameScope(scope).WithNameScope(scope)))
} }
}; };
} }

4
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/StaticResourceExtensionTests.cs

@ -534,12 +534,12 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
{ {
new Setter( new Setter(
Window.TemplateProperty, Window.TemplateProperty,
new FuncControlTemplate<Window>(x => new FuncControlTemplate<Window>((x, scope) =>
new ContentPresenter new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = x[!Window.ContentProperty], [!ContentPresenter.ContentProperty] = x[!Window.ContentProperty],
})) }.RegisterInNameScope(scope).WithNameScope(scope)))
} }
}; };
} }

8
tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs

@ -98,7 +98,7 @@ namespace Avalonia.ReactiveUI.UnitTests
private FuncControlTemplate GetTemplate() private FuncControlTemplate GetTemplate()
{ {
return new FuncControlTemplate<ItemsControl>(parent => return new FuncControlTemplate<ItemsControl>((parent, scope) =>
{ {
return new Border return new Border
{ {
@ -108,9 +108,9 @@ namespace Avalonia.ReactiveUI.UnitTests
Name = "PART_ItemsPresenter", Name = "PART_ItemsPresenter",
MemberSelector = parent.MemberSelector, MemberSelector = parent.MemberSelector,
[~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty], [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
} }.RegisterInNameScope(scope)
}; }.WithNameScope(scope);
}); });
} }
} }
} }

8
tests/Avalonia.ReactiveUI.UnitTests/TransitioningContentControlTest.cs

@ -45,7 +45,7 @@ namespace Avalonia.ReactiveUI.UnitTests
private FuncControlTemplate GetTemplate() private FuncControlTemplate GetTemplate()
{ {
return new FuncControlTemplate<ContentControl>(parent => return new FuncControlTemplate<ContentControl>((parent, scope) =>
{ {
return new Border return new Border
{ {
@ -55,9 +55,9 @@ namespace Avalonia.ReactiveUI.UnitTests
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty], [~ContentPresenter.ContentProperty] = parent[~ContentControl.ContentProperty],
[~ContentPresenter.ContentTemplateProperty] = parent[~ContentControl.ContentTemplateProperty], [~ContentPresenter.ContentTemplateProperty] = parent[~ContentControl.ContentTemplateProperty],
} }.RegisterInNameScope(scope)
}; }.WithNameScope(scope);
}); });
} }
} }
} }

82
tests/Avalonia.Styling.UnitTests/ControlLocatorTests.cs

@ -31,15 +31,19 @@ namespace Avalonia.Styling.UnitTests
} }
} }
}; };
var scope = Register(root, relativeTo);
Register(root, target);
var locator = ControlLocator.Track(relativeTo, "target"); var locator = ControlLocator.Track(relativeTo, "target");
var result = await locator.Take(1); var result = await locator.Take(1);
Assert.Same(target, result); Assert.Same(target, result);
Assert.Equal(0, root.NameScopeRegisteredSubscribers); Assert.Equal(0, scope.RegisteredSubscribers);
Assert.Equal(0, root.NameScopeUnregisteredSubscribers); Assert.Equal(0, scope.UnregisteredSubscribers);
} }
[Fact] [Fact]
public void Track_By_Name_Should_Find_Control_Added_Later() public void Track_By_Name_Should_Find_Control_Added_Later()
{ {
@ -59,6 +63,7 @@ namespace Avalonia.Styling.UnitTests
} }
}) })
}; };
var scope = Register(root, relativeTo);
var locator = ControlLocator.Track(relativeTo, "target"); var locator = ControlLocator.Track(relativeTo, "target");
var target = new TextBlock { Name = "target" }; var target = new TextBlock { Name = "target" };
@ -67,11 +72,12 @@ namespace Avalonia.Styling.UnitTests
using (locator.Subscribe(x => result.Add(x))) using (locator.Subscribe(x => result.Add(x)))
{ {
panel.Children.Add(target); panel.Children.Add(target);
Register(root, target);
} }
Assert.Equal(new[] { null, target }, result); Assert.Equal(new[] { null, target }, result);
Assert.Equal(0, root.NameScopeRegisteredSubscribers); Assert.Equal(0, scope.RegisteredSubscribers);
Assert.Equal(0, root.NameScopeUnregisteredSubscribers); Assert.Equal(0, scope.UnregisteredSubscribers);
} }
[Fact] [Fact]
@ -92,14 +98,18 @@ namespace Avalonia.Styling.UnitTests
} }
} }
}; };
var scope = Register(root, target);
Register(root, relativeTo);
var locator = ControlLocator.Track(relativeTo, "target"); var locator = ControlLocator.Track(relativeTo, "target");
var result = new List<ILogical>(); var result = new List<ILogical>();
locator.Subscribe(x => result.Add(x)); locator.Subscribe(x => result.Add(x));
var other = new TextBlock { Name = "target" }; var other = new TextBlock { Name = "target" };
panel.Children.Remove(target); panel.Children.Remove(target);
scope.Unregister(target.Name);
panel.Children.Add(other); panel.Children.Add(other);
Register(root, other);
Assert.Equal(new[] { target, null, other }, result); Assert.Equal(new[] { target, null, other }, result);
} }
@ -125,6 +135,9 @@ namespace Avalonia.Styling.UnitTests
} }
} }
}; };
var scope1 = Register(root1, relativeTo);
Register(root1, relativeTo);
Register(root1, target1);
var root2 = new TestRoot var root2 = new TestRoot
{ {
@ -136,20 +149,73 @@ namespace Avalonia.Styling.UnitTests
} }
} }
}; };
var scope2 = Register(root2, target2);
var locator = ControlLocator.Track(relativeTo, "target"); var locator = ControlLocator.Track(relativeTo, "target");
var target = new TextBlock { Name = "target" };
var result = new List<ILogical>(); var result = new List<ILogical>();
using (locator.Subscribe(x => result.Add(x))) using (locator.Subscribe(x => result.Add(x)))
{ {
((StackPanel)root1.Child).Children.Remove(relativeTo); ((StackPanel)root1.Child).Children.Remove(relativeTo);
scope1.Unregister(relativeTo.Name);
((StackPanel)root2.Child).Children.Add(relativeTo); ((StackPanel)root2.Child).Children.Add(relativeTo);
Register(root2, relativeTo);
} }
Assert.Equal(new[] { target1, null, target2 }, result); Assert.Equal(new[] { target1, null, target2 }, result);
Assert.Equal(0, root1.NameScopeRegisteredSubscribers); Assert.Equal(0, scope1.RegisteredSubscribers);
Assert.Equal(0, root1.NameScopeUnregisteredSubscribers); Assert.Equal(0, scope1.UnregisteredSubscribers);
Assert.Equal(0, scope2.RegisteredSubscribers);
Assert.Equal(0, scope2.UnregisteredSubscribers);
}
TrackingNameScope Register(StyledElement anchor, StyledElement element)
{
var scope = (TrackingNameScope)NameScope.GetNameScope(anchor);
if (scope == null)
NameScope.SetNameScope(anchor, scope = new TrackingNameScope());
NameScope.Register(anchor, element.Name, element);
return scope;
}
class TrackingNameScope : INameScope
{
public int RegisteredSubscribers { get; private set; }
public int UnregisteredSubscribers { get; private set; }
private NameScope _inner = new NameScope();
public event EventHandler<NameScopeEventArgs> Registered
{
add
{
_inner.Registered += value;
RegisteredSubscribers++;
}
remove
{
_inner.Registered -= value;
RegisteredSubscribers--;
}
}
public event EventHandler<NameScopeEventArgs> Unregistered
{
add
{
_inner.Unregistered += value;
UnregisteredSubscribers++;
}
remove
{
_inner.Unregistered -= value;
UnregisteredSubscribers--;
}
}
public void Register(string name, object element) => _inner.Register(name, element);
public object Find(string name) => _inner.Find(name);
public void Unregister(string name) => _inner.Unregister(name);
} }
} }
} }

12
tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs

@ -16,12 +16,12 @@ namespace Avalonia.Styling.UnitTests
[Fact] [Fact]
public void Named_Template_Child_Of_Control_With_Two_Classes() public void Named_Template_Child_Of_Control_With_Two_Classes()
{ {
var template = new FuncControlTemplate(parent => var template = new FuncControlTemplate((parent, scope) =>
{ {
return new Border return new Border
{ {
Name = "border", Name = "border",
}; }.RegisterInNameScope(scope).WithNameScope(scope);
}); });
var control = new Button var control = new Button
@ -55,12 +55,12 @@ namespace Avalonia.Styling.UnitTests
[Fact] [Fact]
public void Named_OfType_Template_Child_Of_Control_With_Two_Classes_Wrong_Type() public void Named_OfType_Template_Child_Of_Control_With_Two_Classes_Wrong_Type()
{ {
var template = new FuncControlTemplate(parent => var template = new FuncControlTemplate((parent, scope) =>
{ {
return new Border return new Border
{ {
Name = "border", Name = "border",
}; }.RegisterInNameScope(scope).WithNameScope(scope);
}); });
var control = new Button var control = new Button
@ -88,12 +88,12 @@ namespace Avalonia.Styling.UnitTests
[Fact] [Fact]
public void Named_Class_Template_Child_Of_Control() public void Named_Class_Template_Child_Of_Control()
{ {
var template = new FuncControlTemplate(parent => var template = new FuncControlTemplate((parent, scope) =>
{ {
return new Border return new Border
{ {
Name = "border", Name = "border",
}; }.RegisterInNameScope(scope).WithNameScope(scope);
}); });
var control = new Button var control = new Button

13
tests/Avalonia.Styling.UnitTests/SetterTests.cs

@ -51,19 +51,6 @@ namespace Avalonia.Styling.UnitTests
Assert.IsType<Canvas>(control.Child); Assert.IsType<Canvas>(control.Child);
} }
[Fact]
public void Materializes_Template_Should_Be_NameScope()
{
var control = new Decorator();
var template = new FuncTemplate<Canvas>(() => new Canvas());
var style = Mock.Of<IStyle>();
var setter = new Setter(Decorator.ChildProperty, template);
setter.Apply(style, control, null);
Assert.NotNull(NameScope.GetNameScope((Control)control.Child));
}
[Fact] [Fact]
public void Does_Not_Call_Converter_ConvertBack_On_OneWay_Binding() public void Does_Not_Call_Converter_ConvertBack_On_OneWay_Binding()
{ {

15
tests/Avalonia.Styling.UnitTests/StyledElementTests.cs

@ -236,21 +236,6 @@ namespace Avalonia.Styling.UnitTests
} }
} }
[Fact]
public void Adding_To_Logical_Tree_Should_Register_With_NameScope()
{
using (AvaloniaLocator.EnterScope())
{
var root = new TestRoot();
var child = new Border();
child.Name = "foo";
root.Child = child;
Assert.Same(root.FindControl<Border>("foo"), child);
}
}
[Fact] [Fact]
public void Name_Cannot_Be_Set_After_Added_To_Logical_Tree() public void Name_Cannot_Be_Set_After_Added_To_Logical_Tree()
{ {

69
tests/Avalonia.Styling.UnitTests/StyledElementTests_NameScope.cs

@ -1,69 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
{
public class StyledElementTests_NameScope
{
[Fact]
public void Controls_Should_Register_With_NameScope()
{
var root = new TestRoot
{
Child = new Border
{
Name = "foo",
Child = new Border
{
Name = "bar",
}
}
};
root.ApplyTemplate();
Assert.Same(root.FindControl<Border>("foo"), root.Child);
Assert.Same(root.FindControl<Border>("bar"), ((Border)root.Child).Child);
}
[Fact]
public void Control_Should_Unregister_With_NameScope()
{
var root = new TestRoot
{
Child = new Border
{
Name = "foo",
Child = new Border
{
Name = "bar",
}
}
};
root.Child = null;
Assert.Null(root.FindControl<Border>("foo"));
Assert.Null(root.FindControl<Border>("bar"));
}
[Fact]
public void Control_Should_Not_Register_With_Template_NameScope()
{
var root = new TestTemplatedRoot
{
Content = new Border
{
Name = "foo",
}
};
root.ApplyTemplate();
Assert.Null(NameScope.GetNameScope((StyledElement)root.Presenter).Find("foo"));
}
}
}

4
tests/Avalonia.Styling.UnitTests/StyledElementTests_Resources.cs

@ -222,12 +222,12 @@ namespace Avalonia.Controls.UnitTests
private IControlTemplate ContentControlTemplate() private IControlTemplate ContentControlTemplate()
{ {
return new FuncControlTemplate<ContentControl>(x => return new FuncControlTemplate<ContentControl>((x, scope) =>
new ContentPresenter new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = x[!ContentControl.ContentProperty], [!ContentPresenter.ContentProperty] = x[!ContentControl.ContentProperty],
}); }.RegisterInNameScope(scope).WithNameScope(scope));
} }
} }
} }

48
tests/Avalonia.UnitTests/TestRoot.cs

@ -9,11 +9,12 @@ using Avalonia.Media;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Styling; using Avalonia.Styling;
using Avalonia.VisualTree;
using Moq; using Moq;
namespace Avalonia.UnitTests namespace Avalonia.UnitTests
{ {
public class TestRoot : Decorator, IFocusScope, ILayoutRoot, IInputRoot, INameScope, IRenderRoot, IStyleRoot public class TestRoot : Decorator, IFocusScope, ILayoutRoot, IInputRoot, IRenderRoot, IStyleRoot
{ {
private readonly NameScope _nameScope = new NameScope(); private readonly NameScope _nameScope = new NameScope();
@ -28,22 +29,6 @@ namespace Avalonia.UnitTests
Child = child; Child = child;
} }
event EventHandler<NameScopeEventArgs> INameScope.Registered
{
add { _nameScope.Registered += value; ++NameScopeRegisteredSubscribers; }
remove { _nameScope.Registered -= value; --NameScopeRegisteredSubscribers; }
}
public event EventHandler<NameScopeEventArgs> Unregistered
{
add { _nameScope.Unregistered += value; ++NameScopeUnregisteredSubscribers; }
remove { _nameScope.Unregistered -= value; --NameScopeUnregisteredSubscribers; }
}
public int NameScopeRegisteredSubscribers { get; private set; }
public int NameScopeUnregisteredSubscribers { get; private set; }
public Size ClientSize { get; set; } = new Size(100, 100); public Size ClientSize { get; set; } = new Size(100, 100);
public Size MaxClientSize { get; set; } = Size.Infinity; public Size MaxClientSize { get; set; } = Size.Infinity;
@ -94,19 +79,24 @@ namespace Avalonia.UnitTests
public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1); public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1);
void INameScope.Register(string name, object element) public void RegisterChildrenNames()
{ {
_nameScope.Register(name, element); var scope = NameScope.GetNameScope(this) ?? new NameScope();
} NameScope.SetNameScope(this, scope);
void Visit(StyledElement element, bool force = false)
object INameScope.Find(string name) {
{ if (element.Name != null)
return _nameScope.Find(name); {
} if (scope.Find(element.Name) != element)
NameScope.Register(this, element.Name, element);
void INameScope.Unregister(string name) }
{
_nameScope.Unregister(name); if(element is IVisual visual && (force || NameScope.GetNameScope(element) == null))
foreach(var child in visual.GetVisualChildren())
if (child is StyledElement styledChild)
Visit(styledChild);
}
Visit(this, true);
} }
} }
} }

33
tests/Avalonia.UnitTests/TestTemplatedRoot.cs

@ -12,28 +12,16 @@ using Avalonia.Styling;
namespace Avalonia.UnitTests namespace Avalonia.UnitTests
{ {
public class TestTemplatedRoot : ContentControl, ILayoutRoot, INameScope, IRenderRoot, IStyleRoot public class TestTemplatedRoot : ContentControl, ILayoutRoot, IRenderRoot, IStyleRoot
{ {
private readonly NameScope _nameScope = new NameScope(); private readonly NameScope _nameScope = new NameScope();
public TestTemplatedRoot() public TestTemplatedRoot()
{ {
Template = new FuncControlTemplate<TestTemplatedRoot>(x => new ContentPresenter Template = new FuncControlTemplate<TestTemplatedRoot>((x, scope) => new ContentPresenter
{ {
Name = "PART_ContentPresenter", Name = "PART_ContentPresenter",
}); }.RegisterInNameScope(scope).WithNameScope(scope));
}
public event EventHandler<NameScopeEventArgs> Registered
{
add { _nameScope.Registered += value; }
remove { _nameScope.Registered -= value; }
}
public event EventHandler<NameScopeEventArgs> Unregistered
{
add { _nameScope.Unregistered += value; }
remove { _nameScope.Unregistered -= value; }
} }
public Size ClientSize => new Size(100, 100); public Size ClientSize => new Size(100, 100);
@ -63,20 +51,5 @@ namespace Avalonia.UnitTests
public Point PointToClient(PixelPoint p) => p.ToPoint(1); public Point PointToClient(PixelPoint p) => p.ToPoint(1);
public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1); public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1);
void INameScope.Register(string name, object element)
{
_nameScope.Register(name, element);
}
object INameScope.Find(string name)
{
return _nameScope.Find(name);
}
void INameScope.Unregister(string name)
{
_nameScope.Unregister(name);
}
} }
} }

Loading…
Cancel
Save