diff --git a/.ncrunch/Avalonia.Desktop.v3.ncrunchproject b/.ncrunch/Avalonia.Desktop.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.Desktop.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.net461.v3.ncrunchproject b/.ncrunch/Avalonia.net461.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.net461.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/Avalonia.v3.ncrunchsolution b/Avalonia.v3.ncrunchsolution
index 1b5b0c8930..a2208a9a91 100644
--- a/Avalonia.v3.ncrunchsolution
+++ b/Avalonia.v3.ncrunchsolution
@@ -2,6 +2,7 @@
tests\TestFiles\**.*
+ src\Avalonia.Build.Tasks\bin\Debug\netstandard2.0\Avalonia.Build.Tasks.dll
True
.ncrunch
diff --git a/samples/ControlCatalog/Pages/DropDownPage.xaml b/samples/ControlCatalog/Pages/DropDownPage.xaml
index 864d2be49c..7673294e46 100644
--- a/samples/ControlCatalog/Pages/DropDownPage.xaml
+++ b/samples/ControlCatalog/Pages/DropDownPage.xaml
@@ -27,6 +27,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/DropDownPage.xaml.cs b/samples/ControlCatalog/Pages/DropDownPage.xaml.cs
index edab5f1ceb..397f9f21e1 100644
--- a/samples/ControlCatalog/Pages/DropDownPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/DropDownPage.xaml.cs
@@ -13,6 +13,9 @@ namespace ControlCatalog.Pages
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
+ var fontDropDown = this.Find("fontDropDown");
+ fontDropDown.Items = Avalonia.Media.FontFamily.SystemFontFamilies;
+ fontDropDown.SelectedIndex = 0;
}
}
}
diff --git a/src/Avalonia.Animation/AnimationInstance`1.cs b/src/Avalonia.Animation/AnimationInstance`1.cs
index bc7e106a2a..6f601a3e13 100644
--- a/src/Avalonia.Animation/AnimationInstance`1.cs
+++ b/src/Avalonia.Animation/AnimationInstance`1.cs
@@ -19,6 +19,7 @@ namespace Avalonia.Animation
private ulong? _iterationCount;
private ulong _currentIteration;
private bool _gotFirstKFValue;
+ private bool _playbackReversed;
private FillMode _fillMode;
private PlaybackDirection _playbackDirection;
private Animator _animator;
@@ -160,9 +161,14 @@ namespace Avalonia.Animation
_currentIteration = (ulong)(opsTime / iterationTime);
- // Stop animation when the current iteration is beyond the iteration count.
+ // Stop animation when the current iteration is beyond the iteration count
+ // and snap the last iteration value to exact values.
if ((_currentIteration + 1) > _iterationCount)
+ {
+ var easedTime = _easeFunc.Ease(_playbackReversed ? 0.0 : 1.0);
+ _lastInterpValue = _interpolator(easedTime, _neutralValue);
DoComplete();
+ }
if (playbackTime <= iterDuration)
{
@@ -170,27 +176,26 @@ namespace Avalonia.Animation
var normalizedTime = playbackTime / iterDuration;
// Check if normalized time needs to be reversed according to PlaybackDirection
-
- bool playbackReversed;
+
switch (_playbackDirection)
{
case PlaybackDirection.Normal:
- playbackReversed = false;
+ _playbackReversed = false;
break;
case PlaybackDirection.Reverse:
- playbackReversed = true;
+ _playbackReversed = true;
break;
case PlaybackDirection.Alternate:
- playbackReversed = (_currentIteration % 2 == 0) ? false : true;
+ _playbackReversed = (_currentIteration % 2 == 0) ? false : true;
break;
case PlaybackDirection.AlternateReverse:
- playbackReversed = (_currentIteration % 2 == 0) ? true : false;
+ _playbackReversed = (_currentIteration % 2 == 0) ? true : false;
break;
default:
throw new InvalidOperationException($"Animation direction value is unknown: {_playbackDirection}");
}
- if (playbackReversed)
+ if (_playbackReversed)
normalizedTime = 1 - normalizedTime;
// Ease and interpolate
diff --git a/src/Avalonia.OpenGL/EglContext.cs b/src/Avalonia.OpenGL/EglContext.cs
index 27b1abe411..17caf84179 100644
--- a/src/Avalonia.OpenGL/EglContext.cs
+++ b/src/Avalonia.OpenGL/EglContext.cs
@@ -31,14 +31,14 @@ namespace Avalonia.OpenGL
public void MakeCurrent()
{
if (!_egl.MakeCurrent(_disp.Handle, IntPtr.Zero, IntPtr.Zero, Context))
- throw new OpenGlException("eglMakeCurrent failed");
+ throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl);
}
public void MakeCurrent(EglSurface surface)
{
- var surf = ((EglSurface)surface)?.DangerousGetHandle() ?? OffscreenSurface;
+ var surf = surface?.DangerousGetHandle() ?? OffscreenSurface;
if (!_egl.MakeCurrent(_disp.Handle, surf, surf, Context))
- throw new OpenGlException("eglMakeCurrent failed");
+ throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl);
}
}
}
diff --git a/src/Avalonia.OpenGL/EglDisplay.cs b/src/Avalonia.OpenGL/EglDisplay.cs
index 90a70adcb7..2a75e9458e 100644
--- a/src/Avalonia.OpenGL/EglDisplay.cs
+++ b/src/Avalonia.OpenGL/EglDisplay.cs
@@ -1,5 +1,4 @@
using System;
-using System.ComponentModel;
using System.Runtime.InteropServices;
using Avalonia.Platform.Interop;
using static Avalonia.OpenGL.EglConsts;
@@ -34,11 +33,11 @@ namespace Avalonia.OpenGL
if (_display == IntPtr.Zero)
_display = _egl.GetDisplay(IntPtr.Zero);
- if(_display == IntPtr.Zero)
- throw new OpenGlException("eglGetDisplay failed");
-
+ if (_display == IntPtr.Zero)
+ throw OpenGlException.GetFormattedException("eglGetDisplay", _egl);
+
if (!_egl.Initialize(_display, out var major, out var minor))
- throw new OpenGlException("eglInitialize failed");
+ throw OpenGlException.GetFormattedException("eglInitialize", _egl);
foreach (var cfg in new[]
{
@@ -113,7 +112,7 @@ namespace Avalonia.OpenGL
var shareCtx = (EglContext)share;
var ctx = _egl.CreateContext(_display, _config, shareCtx?.Context ?? IntPtr.Zero, _contextAttributes);
if (ctx == IntPtr.Zero)
- throw new OpenGlException("eglCreateContext failed");
+ throw OpenGlException.GetFormattedException("eglCreateContext", _egl);
var surf = _egl.CreatePBufferSurface(_display, _config, new[]
{
EGL_WIDTH, 1,
@@ -121,7 +120,7 @@ namespace Avalonia.OpenGL
EGL_NONE
});
if (surf == IntPtr.Zero)
- throw new OpenGlException("eglCreatePbufferSurface failed");
+ throw OpenGlException.GetFormattedException("eglCreatePBufferSurface", _egl);
var rv = new EglContext(this, _egl, ctx, surf);
rv.MakeCurrent(null);
return rv;
@@ -130,14 +129,14 @@ namespace Avalonia.OpenGL
public void ClearContext()
{
if (!_egl.MakeCurrent(_display, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
- throw new OpenGlException("eglMakeCurrent failed");
+ throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl);
}
public EglSurface CreateWindowSurface(IntPtr window)
{
var s = _egl.CreateWindowSurface(_display, _config, window, new[] {EGL_NONE, EGL_NONE});
if (s == IntPtr.Zero)
- throw new OpenGlException("eglCreateWindowSurface failed");
+ throw OpenGlException.GetFormattedException("eglCreateWindowSurface", _egl);
return new EglSurface(this, _egl, s);
}
diff --git a/src/Avalonia.OpenGL/EglErrors.cs b/src/Avalonia.OpenGL/EglErrors.cs
new file mode 100644
index 0000000000..bfe46f2b69
--- /dev/null
+++ b/src/Avalonia.OpenGL/EglErrors.cs
@@ -0,0 +1,21 @@
+namespace Avalonia.OpenGL
+{
+ public enum EglErrors
+ {
+ EGL_SUCCESS = EglConsts.EGL_SUCCESS,
+ EGL_NOT_INITIALIZED = EglConsts.EGL_NOT_INITIALIZED,
+ EGL_BAD_ACCESS = EglConsts.EGL_BAD_ACCESS,
+ EGL_BAD_ALLOC = EglConsts.EGL_BAD_ALLOC,
+ EGL_BAD_ATTRIBUTE = EglConsts.EGL_BAD_ATTRIBUTE,
+ EGL_BAD_CONTEXT = EglConsts.EGL_BAD_CONTEXT,
+ EGL_BAD_CONFIG = EglConsts.EGL_BAD_CONFIG,
+ EGL_BAD_CURRENT_SURFACE = EglConsts.EGL_BAD_CURRENT_SURFACE,
+ EGL_BAD_DISPLAY = EglConsts.EGL_BAD_DISPLAY,
+ EGL_BAD_SURFACE = EglConsts.EGL_BAD_SURFACE,
+ EGL_BAD_MATCH = EglConsts.EGL_BAD_MATCH,
+ EGL_BAD_PARAMETER = EglConsts.EGL_BAD_PARAMETER,
+ EGL_BAD_NATIVE_PIXMAP = EglConsts.EGL_BAD_NATIVE_PIXMAP,
+ EGL_BAD_NATIVE_WINDOW = EglConsts.EGL_BAD_NATIVE_WINDOW,
+ EGL_CONTEXT_LOST = EglConsts.EGL_CONTEXT_LOST
+ }
+}
diff --git a/src/Avalonia.OpenGL/EglInterface.cs b/src/Avalonia.OpenGL/EglInterface.cs
index 535f66ee1f..c41a01340c 100644
--- a/src/Avalonia.OpenGL/EglInterface.cs
+++ b/src/Avalonia.OpenGL/EglInterface.cs
@@ -1,7 +1,6 @@
using System;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
-using static Avalonia.OpenGL.EglConsts;
namespace Avalonia.OpenGL
{
@@ -32,8 +31,12 @@ namespace Avalonia.OpenGL
var lib = dyn.LoadLibrary(library);
return (s, o) => dyn.GetProcAddress(lib, s, o);
}
-
+
// ReSharper disable UnassignedGetOnlyAutoProperty
+ public delegate int EglGetError();
+ [EntryPoint("eglGetError")]
+ public EglGetError GetError { get; }
+
public delegate IntPtr EglGetDisplay(IntPtr nativeDisplay);
[EntryPoint("eglGetDisplay")]
public EglGetDisplay GetDisplay { get; }
diff --git a/src/Avalonia.OpenGL/GlConsts.cs b/src/Avalonia.OpenGL/GlConsts.cs
index 3084a6f958..275f351e3e 100644
--- a/src/Avalonia.OpenGL/GlConsts.cs
+++ b/src/Avalonia.OpenGL/GlConsts.cs
@@ -456,12 +456,15 @@ namespace Avalonia.OpenGL
public const int GL_RENDERER = 0x1F01;
public const int GL_VERSION = 0x1F02;
public const int GL_EXTENSIONS = 0x1F03;
+ public const int GL_NO_ERROR = 0;
public const int GL_INVALID_ENUM = 0x0500;
public const int GL_INVALID_VALUE = 0x0501;
public const int GL_INVALID_OPERATION = 0x0502;
public const int GL_STACK_OVERFLOW = 0x0503;
public const int GL_STACK_UNDERFLOW = 0x0504;
public const int GL_OUT_OF_MEMORY = 0x0505;
+ public const int GL_INVALID_FRAMEBUFFER_OPERATION = 0x0506;
+ public const int GL_CONTEXT_LOST = 0x0507;
public const int GL_CURRENT_BIT = 0x00000001;
public const int GL_POINT_BIT = 0x00000002;
public const int GL_LINE_BIT = 0x00000004;
diff --git a/src/Avalonia.OpenGL/GlErrors.cs b/src/Avalonia.OpenGL/GlErrors.cs
new file mode 100644
index 0000000000..ecc7d21c7a
--- /dev/null
+++ b/src/Avalonia.OpenGL/GlErrors.cs
@@ -0,0 +1,15 @@
+namespace Avalonia.OpenGL
+{
+ public enum GlErrors
+ {
+ GL_NO_ERROR = GlConsts.GL_NO_ERROR,
+ GL_INVALID_ENUM = GlConsts.GL_INVALID_ENUM,
+ GL_INVALID_VALUE = GlConsts.GL_INVALID_VALUE,
+ GL_INVALID_OPERATION = GlConsts.GL_INVALID_OPERATION,
+ GL_INVALID_FRAMEBUFFER_OPERATION = GlConsts.GL_INVALID_FRAMEBUFFER_OPERATION,
+ GL_STACK_OVERFLOW = GlConsts.GL_STACK_OVERFLOW,
+ GL_STACK_UNDERFLOW = GlConsts.GL_STACK_UNDERFLOW,
+ GL_OUT_OF_MEMORY = GlConsts.GL_OUT_OF_MEMORY,
+ GL_CONTEXT_LOST = GlConsts.GL_CONTEXT_LOST
+ }
+}
diff --git a/src/Avalonia.OpenGL/GlInterface.cs b/src/Avalonia.OpenGL/GlInterface.cs
index 60dc5381d4..f23e1c5829 100644
--- a/src/Avalonia.OpenGL/GlInterface.cs
+++ b/src/Avalonia.OpenGL/GlInterface.cs
@@ -19,7 +19,10 @@ namespace Avalonia.OpenGL
public T GetProcAddress(string proc) => Marshal.GetDelegateForFunctionPointer(GetProcAddress(proc));
// ReSharper disable UnassignedGetOnlyAutoProperty
-
+ public delegate int GlGetError();
+ [EntryPoint("glGetError")]
+ public GlGetError GetError { get; }
+
public delegate void GlClearStencil(int s);
[EntryPoint("glClearStencil")]
public GlClearStencil ClearStencil { get; }
diff --git a/src/Avalonia.OpenGL/OpenGlException.cs b/src/Avalonia.OpenGL/OpenGlException.cs
index 7ba539a2b2..d3cd7d059e 100644
--- a/src/Avalonia.OpenGL/OpenGlException.cs
+++ b/src/Avalonia.OpenGL/OpenGlException.cs
@@ -4,9 +4,39 @@ namespace Avalonia.OpenGL
{
public class OpenGlException : Exception
{
+ public int? ErrorCode { get; private set; }
+
public OpenGlException(string message) : base(message)
{
+ }
+
+ private OpenGlException(string message, int errorCode) : base(message)
+ {
+ ErrorCode = errorCode;
+ }
+
+ public static OpenGlException GetFormattedException(string funcName, EglInterface egl)
+ {
+ return GetFormattedException(typeof(EglErrors), funcName, egl.GetError());
+ }
+
+ public static OpenGlException GetFormattedException(string funcName, GlInterface gl)
+ {
+ return GetFormattedException(typeof(GlErrors), funcName, gl.GetError());
+ }
+ private static OpenGlException GetFormattedException(Type consts, string funcName, int errorCode)
+ {
+ try
+ {
+ string errorName = Enum.GetName(consts, errorCode);
+ return new OpenGlException(
+ $"{funcName} failed with error {errorName} (0x{errorCode.ToString("X")})", errorCode);
+ }
+ catch (ArgumentException)
+ {
+ return new OpenGlException($"{funcName} failed with error 0x{errorCode.ToString("X")}", errorCode);
+ }
}
}
}
diff --git a/src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs b/src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs
index cd019e6535..362ac86e50 100644
--- a/src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs
+++ b/src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs
@@ -116,11 +116,9 @@ namespace Avalonia.Styling
}
}
- if (Name != null)
+ if (Name != null && control.Name != Name)
{
- return control.Name == Name ?
- SelectorMatch.AlwaysThisInstance :
- SelectorMatch.NeverThisInstance;
+ return SelectorMatch.NeverThisInstance;
}
if (_classes.IsValueCreated && _classes.Value.Count > 0)
@@ -130,17 +128,13 @@ namespace Avalonia.Styling
var observable = new ClassObserver(control.Classes, _classes.Value);
return new SelectorMatch(observable);
}
- else
+ else if (!Matches(control.Classes))
{
- return Matches(control.Classes) ?
- SelectorMatch.AlwaysThisInstance :
- SelectorMatch.NeverThisInstance;
+ return SelectorMatch.NeverThisInstance;
}
}
- else
- {
- return SelectorMatch.AlwaysThisType;
- }
+
+ return Name == null ? SelectorMatch.AlwaysThisType : SelectorMatch.AlwaysThisInstance;
}
protected override Selector MovePrevious() => _previous;
diff --git a/src/Avalonia.Visuals/Media/FontFamily.cs b/src/Avalonia.Visuals/Media/FontFamily.cs
index 0ba25e6c0d..5c152cd8a0 100644
--- a/src/Avalonia.Visuals/Media/FontFamily.cs
+++ b/src/Avalonia.Visuals/Media/FontFamily.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Media.Fonts;
+using Avalonia.Platform;
namespace Avalonia.Media
{
@@ -51,6 +52,12 @@ namespace Avalonia.Media
///
public static FontFamily Default => new FontFamily(String.Empty);
+ ///
+ /// Represents all font families in the system. This can be an expensive call depending on platform implementation.
+ ///
+ public static IEnumerable SystemFontFamilies =>
+ AvaloniaLocator.Current.GetService().InstalledFontNames.Select(name => new FontFamily(name));
+
///
/// Gets the primary family name of the font family.
///
diff --git a/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs b/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs
index aacdef0538..3a1f79e32a 100644
--- a/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs
+++ b/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs
@@ -13,6 +13,11 @@ namespace Avalonia.Platform
///
public interface IPlatformRenderInterface
{
+ ///
+ /// Get all installed fonts in the system
+ ///
+ IEnumerable InstalledFontNames { get; }
+
///
/// Creates a formatted text implementation.
///
diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
index 9b10d74c64..8080c27831 100644
--- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
+++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
@@ -19,6 +19,8 @@ namespace Avalonia.Skia
{
private GRContext GrContext { get; }
+ public IEnumerable InstalledFontNames => SKFontManager.Default.FontFamilies;
+
public PlatformRenderInterface()
{
var gl = AvaloniaLocator.Current.GetService();
diff --git a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
index 3ec18dac5e..8412a65e23 100644
--- a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
+++ b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
@@ -41,6 +41,19 @@ namespace Avalonia.Direct2D1
public static SharpDX.DXGI.Device1 DxgiDevice { get; private set; }
+ public IEnumerable InstalledFontNames
+ {
+ get
+ {
+ var cache = Direct2D1FontCollectionCache.s_installedFontCollection;
+ var length = cache.FontFamilyCount;
+ for (int i = 0; i < length; i++)
+ {
+ var names = cache.GetFontFamily(i).FamilyNames;
+ yield return names.GetString(0);
+ }
+ }
+ }
private static readonly object s_initLock = new object();
private static bool s_initialized = false;
diff --git a/src/Windows/Avalonia.Direct2D1/Media/Direct2D1FontCollectionCache.cs b/src/Windows/Avalonia.Direct2D1/Media/Direct2D1FontCollectionCache.cs
index d60aa15a5e..d93a59d384 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/Direct2D1FontCollectionCache.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/Direct2D1FontCollectionCache.cs
@@ -7,7 +7,7 @@ namespace Avalonia.Direct2D1.Media
internal static class Direct2D1FontCollectionCache
{
private static readonly ConcurrentDictionary s_cachedCollections;
- private static readonly SharpDX.DirectWrite.FontCollection s_installedFontCollection;
+ internal static readonly SharpDX.DirectWrite.FontCollection s_installedFontCollection;
static Direct2D1FontCollectionCache()
{
diff --git a/tests/Avalonia.Animation.UnitTests/AnimationIterationTests.cs b/tests/Avalonia.Animation.UnitTests/AnimationIterationTests.cs
index d89b8469df..f7a8774689 100644
--- a/tests/Avalonia.Animation.UnitTests/AnimationIterationTests.cs
+++ b/tests/Avalonia.Animation.UnitTests/AnimationIterationTests.cs
@@ -8,6 +8,7 @@ using Avalonia.Styling;
using Avalonia.UnitTests;
using Avalonia.Data;
using Xunit;
+using Avalonia.Animation.Easings;
namespace Avalonia.Animation.UnitTests
{
@@ -73,5 +74,58 @@ namespace Avalonia.Animation.UnitTests
Assert.True(animationRun.Status == TaskStatus.RanToCompletion);
Assert.Equal(border.Width, 100d);
}
+
+ [Fact]
+ public void Check_FillModes_Start_and_End_Values_if_Retained()
+ {
+ var keyframe1 = new KeyFrame()
+ {
+ Setters =
+ {
+ new Setter(Border.WidthProperty, 0d),
+ },
+ Cue = new Cue(0.0d)
+ };
+
+ var keyframe2 = new KeyFrame()
+ {
+ Setters =
+ {
+ new Setter(Border.WidthProperty, 300d),
+ },
+ Cue = new Cue(1.0d)
+ };
+
+ var animation = new Animation()
+ {
+ Duration = TimeSpan.FromSeconds(0.05d),
+ Delay = TimeSpan.FromSeconds(0.05d),
+ Easing = new SineEaseInOut(),
+ FillMode = FillMode.Both,
+ Children =
+ {
+ keyframe1,
+ keyframe2
+ }
+ };
+
+ var border = new Border()
+ {
+ Height = 100d,
+ Width = 100d,
+ };
+
+ var clock = new TestClock();
+ var animationRun = animation.RunAsync(border, clock);
+
+ clock.Step(TimeSpan.FromSeconds(0d));
+ Assert.Equal(border.Width, 0d);
+
+ clock.Step(TimeSpan.FromSeconds(0.050d));
+ Assert.Equal(border.Width, 0d);
+
+ clock.Step(TimeSpan.FromSeconds(0.100d));
+ Assert.Equal(border.Width, 300d);
+ }
}
}
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
index 04b29376b0..ba9b443d92 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
@@ -85,6 +85,44 @@ namespace Avalonia.Styling.UnitTests
Assert.Equal(SelectorMatchResult.NeverThisType, match.Result);
}
+ [Fact]
+ public void Named_Class_Template_Child_Of_Control()
+ {
+ var template = new FuncControlTemplate(parent =>
+ {
+ return new Border
+ {
+ Name = "border",
+ };
+ });
+
+ var control = new Button
+ {
+ Template = template,
+ };
+
+ control.ApplyTemplate();
+
+ var selector = default(Selector)
+ .OfType