Browse Source

Merge branch 'master' into fixes/2512-xaml-namescope-registration

pull/2515/head
Steven Kirk 7 years ago
committed by GitHub
parent
commit
9db24f77c2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .gitignore
  2. 3
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  3. 2
      src/Avalonia.Controls/Application.cs
  4. 29
      src/Avalonia.Controls/Expander.cs
  5. 18
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  6. 14
      src/Avalonia.Controls/Window.cs
  7. 27
      src/Avalonia.Input/MouseDevice.cs
  8. 2
      src/Avalonia.Styling/Controls/IResourceProvider.cs
  9. 2
      src/Avalonia.Styling/Controls/ResourceDictionary.cs
  10. 10
      src/Avalonia.Styling/Controls/ResourceProviderExtensions.cs
  11. 2
      src/Avalonia.Styling/StyledElement.cs
  12. 2
      src/Avalonia.Styling/Styling/Style.cs
  13. 2
      src/Avalonia.Styling/Styling/Styles.cs
  14. 2
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
  15. 2
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs
  16. 2
      src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs
  17. 24
      src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  18. 18
      src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
  19. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github
  20. 133
      tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
  21. 3
      tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
  22. 6
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithCustomProperty.xaml
  23. 79
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs

2
.gitignore

@ -196,3 +196,5 @@ ModuleCache.noindex/
Build/Intermediates.noindex/
info.plist
build-intermediate
obj-Direct2D1/
obj-Skia/

3
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

@ -150,7 +150,8 @@ namespace Avalonia.Build.Tasks
classType = typeSystem.TargetAssembly.FindType(tn.Text);
if (classType == null)
throw new XamlIlParseException($"Unable to find type `{tn.Text}`", classDirective);
initialRoot.Type = new XamlIlAstClrTypeReference(classDirective, classType, false);
compiler.OverrideRootType(parsed,
new XamlIlAstClrTypeReference(classDirective, classType, false));
initialRoot.Children.Remove(classDirective);
}

2
src/Avalonia.Controls/Application.cs

@ -362,7 +362,7 @@ namespace Avalonia
}
/// <inheritdoc/>
bool IResourceProvider.TryGetResource(string key, out object value)
bool IResourceProvider.TryGetResource(object key, out object value)
{
value = null;
return (_resources?.TryGetResource(key, out value) ?? false) ||

29
src/Avalonia.Controls/Expander.cs

@ -13,18 +13,11 @@ namespace Avalonia.Controls
public class Expander : HeaderedContentControl
{
public static readonly DirectProperty<Expander, IPageTransition> ContentTransitionProperty =
AvaloniaProperty.RegisterDirect<Expander, IPageTransition>(
nameof(ContentTransition),
o => o.ContentTransition,
(o, v) => o.ContentTransition = v);
public static readonly StyledProperty<IPageTransition> ContentTransitionProperty =
AvaloniaProperty.Register<Expander, IPageTransition>(nameof(ContentTransition));
public static readonly DirectProperty<Expander, ExpandDirection> ExpandDirectionProperty =
AvaloniaProperty.RegisterDirect<Expander, ExpandDirection>(
nameof(ExpandDirection),
o => o.ExpandDirection,
(o, v) => o.ExpandDirection = v,
ExpandDirection.Down);
public static readonly StyledProperty<ExpandDirection> ExpandDirectionProperty =
AvaloniaProperty.Register<Expander, ExpandDirection>(nameof(ExpandDirection), ExpandDirection.Down);
public static readonly DirectProperty<Expander, bool> IsExpandedProperty =
AvaloniaProperty.RegisterDirect<Expander, bool>(
@ -33,6 +26,8 @@ namespace Avalonia.Controls
(o, v) => o.IsExpanded = v,
defaultBindingMode: Data.BindingMode.TwoWay);
private bool _isExpanded;
static Expander()
{
PseudoClass<Expander, ExpandDirection>(ExpandDirectionProperty, d => d == ExpandDirection.Down, ":down");
@ -47,14 +42,14 @@ namespace Avalonia.Controls
public IPageTransition ContentTransition
{
get { return _contentTransition; }
set { SetAndRaise(ContentTransitionProperty, ref _contentTransition, value); }
get => GetValue(ContentTransitionProperty);
set => SetValue(ContentTransitionProperty, value);
}
public ExpandDirection ExpandDirection
{
get { return _expandDirection; }
set { SetAndRaise(ExpandDirectionProperty, ref _expandDirection, value); }
get => GetValue(ExpandDirectionProperty);
set => SetValue(ExpandDirectionProperty, value);
}
public bool IsExpanded
@ -79,9 +74,5 @@ namespace Avalonia.Controls
}
}
}
private IPageTransition _contentTransition;
private ExpandDirection _expandDirection;
private bool _isExpanded;
}
}

18
src/Avalonia.Controls/Primitives/SelectingItemsControl.cs

@ -644,20 +644,20 @@ namespace Avalonia.Controls.Primitives
/// <param name="desired">The desired items.</param>
internal static void SynchronizeItems(IList items, IEnumerable<object> desired)
{
int index = 0;
var index = 0;
foreach (var i in desired)
foreach (object item in desired)
{
if (index < items.Count)
int itemIndex = items.IndexOf(item);
if (itemIndex == -1)
{
if (items[index] != i)
{
items[index] = i;
}
items.Insert(index, item);
}
else
else if(itemIndex != index)
{
items.Add(i);
items.RemoveAt(itemIndex);
items.Insert(index, item);
}
++index;

14
src/Avalonia.Controls/Window.cs

@ -330,8 +330,7 @@ namespace Avalonia.Controls
protected virtual bool HandleClosing()
{
var args = new CancelEventArgs();
Closing?.Invoke(this, args);
OnClosing(args);
return args.Cancel;
}
@ -576,6 +575,17 @@ namespace Avalonia.Controls
base.HandleResized(clientSize);
}
/// <summary>
/// Raises the <see cref="Closing"/> event.
/// </summary>
/// <param name="e">The event args.</param>
/// <remarks>
/// A type that derives from <see cref="Window"/> may override <see cref="OnClosing"/>. The
/// overridden method must call <see cref="OnClosing"/> on the base class if the
/// <see cref="Closing"/> event needs to be raised.
/// </remarks>
protected virtual void OnClosing(CancelEventArgs e) => Closing?.Invoke(this, e);
}
}

27
src/Avalonia.Input/MouseDevice.cs

@ -108,11 +108,11 @@ namespace Avalonia.Input
{
if (Captured == null)
{
SetPointerOver(this, root, clientPoint);
SetPointerOver(this, root, clientPoint, InputModifiers.None);
}
else
{
SetPointerOver(this, root, Captured);
SetPointerOver(this, root, Captured, InputModifiers.None);
}
}
}
@ -128,7 +128,7 @@ namespace Avalonia.Input
switch (e.Type)
{
case RawMouseEventType.LeaveWindow:
LeaveWindow(mouse, e.Root);
LeaveWindow(mouse, e.Root, e.InputModifiers);
break;
case RawMouseEventType.LeftButtonDown:
case RawMouseEventType.RightButtonDown:
@ -157,12 +157,12 @@ namespace Avalonia.Input
}
}
private void LeaveWindow(IMouseDevice device, IInputRoot root)
private void LeaveWindow(IMouseDevice device, IInputRoot root, InputModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
ClearPointerOver(this, root);
ClearPointerOver(this, root, inputModifiers);
}
private bool MouseDown(IMouseDevice device, ulong timestamp, IInputElement root, Point p, MouseButton button, InputModifiers inputModifiers)
@ -218,11 +218,11 @@ namespace Avalonia.Input
if (Captured == null)
{
source = SetPointerOver(this, root, p);
source = SetPointerOver(this, root, p, inputModifiers);
}
else
{
SetPointerOver(this, root, Captured);
SetPointerOver(this, root, Captured, inputModifiers);
source = Captured;
}
@ -306,7 +306,7 @@ namespace Avalonia.Input
return Captured ?? root.InputHitTest(p);
}
private void ClearPointerOver(IPointerDevice device, IInputRoot root)
private void ClearPointerOver(IPointerDevice device, IInputRoot root, InputModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
@ -316,6 +316,7 @@ namespace Avalonia.Input
{
RoutedEvent = InputElement.PointerLeaveEvent,
Device = device,
InputModifiers = inputModifiers
};
if (element!=null && !element.IsAttachedToVisualTree)
@ -353,7 +354,7 @@ namespace Avalonia.Input
}
}
private IInputElement SetPointerOver(IPointerDevice device, IInputRoot root, Point p)
private IInputElement SetPointerOver(IPointerDevice device, IInputRoot root, Point p, InputModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
@ -364,18 +365,18 @@ namespace Avalonia.Input
{
if (element != null)
{
SetPointerOver(device, root, element);
SetPointerOver(device, root, element, inputModifiers);
}
else
{
ClearPointerOver(device, root);
ClearPointerOver(device, root, inputModifiers);
}
}
return element;
}
private void SetPointerOver(IPointerDevice device, IInputRoot root, IInputElement element)
private void SetPointerOver(IPointerDevice device, IInputRoot root, IInputElement element, InputModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
@ -383,7 +384,7 @@ namespace Avalonia.Input
IInputElement branch = null;
var e = new PointerEventArgs { Device = device, };
var e = new PointerEventArgs { Device = device, InputModifiers = inputModifiers };
var el = element;
while (el != null)

2
src/Avalonia.Styling/Controls/IResourceProvider.cs

@ -28,6 +28,6 @@ namespace Avalonia.Controls
/// <returns>
/// True if the resource if found, otherwise false.
/// </returns>
bool TryGetResource(string key, out object value);
bool TryGetResource(object key, out object value);
}
}

2
src/Avalonia.Styling/Controls/ResourceDictionary.cs

@ -69,7 +69,7 @@ namespace Avalonia.Controls
}
/// <inheritdoc/>
public bool TryGetResource(string key, out object value)
public bool TryGetResource(object key, out object value)
{
if (TryGetValue(key, out value))
{

10
src/Avalonia.Styling/Controls/ResourceProviderExtensions.cs

@ -11,7 +11,7 @@ namespace Avalonia.Controls
/// <param name="control">The control.</param>
/// <param name="key">The resource key.</param>
/// <returns>The resource, or <see cref="AvaloniaProperty.UnsetValue"/> if not found.</returns>
public static object FindResource(this IResourceNode control, string key)
public static object FindResource(this IResourceNode control, object key)
{
if (control.TryFindResource(key, out var value))
{
@ -28,7 +28,7 @@ namespace Avalonia.Controls
/// <param name="key">The resource key.</param>
/// <param name="value">On return, contains the resource if found, otherwise null.</param>
/// <returns>True if the resource was found; otherwise false.</returns>
public static bool TryFindResource(this IResourceNode control, string key, out object value)
public static bool TryFindResource(this IResourceNode control, object key, out object value)
{
Contract.Requires<ArgumentNullException>(control != null);
Contract.Requires<ArgumentNullException>(key != null);
@ -52,7 +52,7 @@ namespace Avalonia.Controls
return false;
}
public static IObservable<object> GetResourceObservable(this IResourceNode target, string key)
public static IObservable<object> GetResourceObservable(this IResourceNode target, object key)
{
return new ResourceObservable(target, key);
}
@ -60,9 +60,9 @@ namespace Avalonia.Controls
private class ResourceObservable : LightweightObservableBase<object>
{
private readonly IResourceNode _target;
private readonly string _key;
private readonly object _key;
public ResourceObservable(IResourceNode target, string key)
public ResourceObservable(IResourceNode target, object key)
{
_target = target;
_key = key;

2
src/Avalonia.Styling/StyledElement.cs

@ -415,7 +415,7 @@ namespace Avalonia
}
/// <inheritdoc/>
bool IResourceProvider.TryGetResource(string key, out object value)
bool IResourceProvider.TryGetResource(object key, out object value)
{
value = null;
return (_resources?.TryGetResource(key, out value) ?? false) ||

2
src/Avalonia.Styling/Styling/Style.cs

@ -171,7 +171,7 @@ namespace Avalonia.Styling
}
/// <inheritdoc/>
public bool TryGetResource(string key, out object result)
public bool TryGetResource(object key, out object result)
{
result = null;
return _resources?.TryGetResource(key, out result) ?? false;

2
src/Avalonia.Styling/Styling/Styles.cs

@ -178,7 +178,7 @@ namespace Avalonia.Styling
}
/// <inheritdoc/>
public bool TryGetResource(string key, out object value)
public bool TryGetResource(object key, out object value)
{
if (_resources != null && _resources.TryGetValue(key, out value))
{

2
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs

@ -26,7 +26,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
ResourceKey = resourceKey;
}
public string ResourceKey { get; set; }
public object ResourceKey { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) => ProvideTypedValue(serviceProvider);

2
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ResourceInclude.cs

@ -47,7 +47,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
bool IResourceProvider.HasResources => Loaded.HasResources;
/// <inhertidoc/>
bool IResourceProvider.TryGetResource(string key, out object value)
bool IResourceProvider.TryGetResource(object key, out object value)
{
return Loaded.TryGetResource(key, out value);
}

2
src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs

@ -86,7 +86,7 @@ namespace Avalonia.Markup.Xaml.Styling
}
/// <inheritdoc/>
public bool TryGetResource(string key, out object value) => Loaded.TryGetResource(key, out value);
public bool TryGetResource(object key, out object value) => Loaded.TryGetResource(key, out value);
/// <inheritdoc/>
void ISetStyleParent.NotifyResourcesChanged(ResourcesChangedEventArgs e)

24
src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlCompiler.cs

@ -112,13 +112,31 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
rootType = new XamlIlAstClrTypeReference(rootObject, overrideRootType, false);
}
rootObject.Type = rootType;
OverrideRootType(parsed, rootType);
Transform(parsed);
Compile(parsed, tb, _contextType, PopulateName, BuildName, "__AvaloniaXamlIlNsInfo", baseUri, fileSource);
}
public void OverrideRootType(XamlIlDocument doc, IXamlIlAstTypeReference newType)
{
var root = (XamlIlAstObjectNode)doc.Root;
var oldType = root.Type;
if (oldType.Equals(newType))
return;
root.Type = newType;
foreach (var child in root.Children.OfType<XamlIlAstXamlPropertyValueNode>())
{
if (child.Property is XamlIlAstNamePropertyReference prop)
{
if (prop.DeclaringType.Equals(oldType))
prop.DeclaringType = newType;
if (prop.TargetType.Equals(oldType))
prop.TargetType = newType;
}
}
}
}
}

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

@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Data;
using Portable.Xaml;
using Portable.Xaml.Markup;
// ReSharper disable UnusedMember.Global
// ReSharper disable UnusedParameter.Global
@ -17,19 +18,24 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
{
var resourceNodes = provider.GetService<IAvaloniaXamlIlParentStackProvider>().Parents
.OfType<IResourceNode>().ToList();
return sp => builder(new DeferredParentServiceProvider(sp, resourceNodes));
var rootObject = provider.GetService<IRootObjectProvider>().RootObject;
return sp => builder(new DeferredParentServiceProvider(sp, resourceNodes, rootObject));
}
class DeferredParentServiceProvider : IAvaloniaXamlIlParentStackProvider, IServiceProvider
class DeferredParentServiceProvider :
IAvaloniaXamlIlParentStackProvider,
IServiceProvider,
IRootObjectProvider
{
private readonly IServiceProvider _parentProvider;
private readonly List<IResourceNode> _parentResourceNodes;
public DeferredParentServiceProvider(IServiceProvider parentProvider, List<IResourceNode> parentResourceNodes)
public DeferredParentServiceProvider(IServiceProvider parentProvider, List<IResourceNode> parentResourceNodes,
object rootObject)
{
_parentProvider = parentProvider;
_parentResourceNodes = parentResourceNodes;
RootObject = rootObject;
}
public IEnumerable<object> Parents => GetParents();
@ -46,8 +52,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
{
if (serviceType == typeof(IAvaloniaXamlIlParentStackProvider))
return this;
if (serviceType == typeof(IRootObjectProvider))
return this;
return _parentProvider?.GetService(serviceType);
}
public object RootObject { get; }
}

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

@ -1 +1 @@
Subproject commit 3b3c1f93a566080d417b9782f9cc4ea67cd62344
Subproject commit 1e3ffc315401f0b2eb96a0e79b25c2fc19a80d78

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

@ -10,6 +10,7 @@ using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Data.Core;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.LogicalTree;
using Avalonia.UnitTests;
using Xunit;
@ -425,7 +426,6 @@ namespace Avalonia.Controls.UnitTests
Assert.True(called);
}
[Fact]
public void LogicalChildren_Should_Be_Set()
{
@ -623,6 +623,135 @@ namespace Avalonia.Controls.UnitTests
}
}
[Fact]
public void Pressing_SelectAll_Gesture_Should_Select_All_Nodes()
{
using (UnitTestApplication.Start())
{
var tree = CreateTestTreeData();
var target = new TreeView
{
Template = CreateTreeViewTemplate(),
Items = tree,
SelectionMode = SelectionMode.Multiple
};
var visualRoot = new TestRoot();
visualRoot.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target);
var rootNode = tree[0];
var keymap = AvaloniaLocator.Current.GetService<PlatformHotkeyConfiguration>();
var selectAllGesture = keymap.SelectAll.First();
var keyEvent = new KeyEventArgs
{
RoutedEvent = InputElement.KeyDownEvent,
Key = selectAllGesture.Key,
Modifiers = selectAllGesture.Modifiers
};
target.RaiseEvent(keyEvent);
TreeTestHelper.AssertChildrenSelected(target, rootNode);
}
}
[Fact]
public void Pressing_SelectAll_Gesture_With_Downward_Range_Selected_Should_Select_All_Nodes()
{
using (UnitTestApplication.Start())
{
var tree = CreateTestTreeData();
var target = new TreeView
{
Template = CreateTreeViewTemplate(),
Items = tree,
SelectionMode = SelectionMode.Multiple
};
var visualRoot = new TestRoot();
visualRoot.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target);
var rootNode = tree[0];
var from = rootNode.Children[0];
var to = rootNode.Children.Last();
var fromContainer = (TreeViewItem)target.ItemContainerGenerator.Index.ContainerFromItem(from);
var toContainer = (TreeViewItem)target.ItemContainerGenerator.Index.ContainerFromItem(to);
TreeTestHelper.ClickContainer(fromContainer, InputModifiers.None);
TreeTestHelper.ClickContainer(toContainer, InputModifiers.Shift);
var keymap = AvaloniaLocator.Current.GetService<PlatformHotkeyConfiguration>();
var selectAllGesture = keymap.SelectAll.First();
var keyEvent = new KeyEventArgs
{
RoutedEvent = InputElement.KeyDownEvent,
Key = selectAllGesture.Key,
Modifiers = selectAllGesture.Modifiers
};
target.RaiseEvent(keyEvent);
TreeTestHelper.AssertChildrenSelected(target, rootNode);
}
}
[Fact]
public void Pressing_SelectAll_Gesture_With_Upward_Range_Selected_Should_Select_All_Nodes()
{
using (UnitTestApplication.Start())
{
var tree = CreateTestTreeData();
var target = new TreeView
{
Template = CreateTreeViewTemplate(),
Items = tree,
SelectionMode = SelectionMode.Multiple
};
var visualRoot = new TestRoot();
visualRoot.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target);
var rootNode = tree[0];
var from = rootNode.Children.Last();
var to = rootNode.Children[0];
var fromContainer = (TreeViewItem)target.ItemContainerGenerator.Index.ContainerFromItem(from);
var toContainer = (TreeViewItem)target.ItemContainerGenerator.Index.ContainerFromItem(to);
TreeTestHelper.ClickContainer(fromContainer, InputModifiers.None);
TreeTestHelper.ClickContainer(toContainer, InputModifiers.Shift);
var keymap = AvaloniaLocator.Current.GetService<PlatformHotkeyConfiguration>();
var selectAllGesture = keymap.SelectAll.First();
var keyEvent = new KeyEventArgs
{
RoutedEvent = InputElement.KeyDownEvent,
Key = selectAllGesture.Key,
Modifiers = selectAllGesture.Modifiers
};
target.RaiseEvent(keyEvent);
TreeTestHelper.AssertChildrenSelected(target, rootNode);
}
}
private void ApplyTemplates(TreeView tree)
{
tree.ApplyTemplate();
@ -765,7 +894,7 @@ namespace Avalonia.Controls.UnitTests
}
}
private class Node : NotifyingBase
private class Node : NotifyingBase
{
private IAvaloniaList<Node> _children;

3
tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj

@ -32,7 +32,8 @@
<EmbeddedResource Include="Xaml\Style2.xaml">
<SubType>Designer</SubType>
</EmbeddedResource>
<AvaloniaResource Include="Xaml\XamlIlClassWithPrecompiledXaml.xaml"/>
<AvaloniaResource Include="Xaml\XamlIlClassWithPrecompiledXaml.xaml" />
<AvaloniaResource Include="Xaml\XamlIlClassWithCustomProperty.xaml" />
</ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" />
</Project>

6
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlClassWithCustomProperty.xaml

@ -0,0 +1,6 @@
<UserControl xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
x:Class='Avalonia.Markup.Xaml.UnitTests.XamlIlClassWithCustomProperty'
Test="123">
</UserControl>

79
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs

@ -5,8 +5,12 @@ using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Data.Converters;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Threading;
using Avalonia.UnitTests;
using Avalonia.VisualTree;
using JetBrains.Annotations;
@ -117,6 +121,81 @@ namespace Avalonia.Markup.Xaml.UnitTests
Assert.Equal(Brushes.Red.Color, ((ISolidColorBrush)canvas.Background).Color);
}
}
[Fact]
public void Event_Handlers_Should_Work_For_Templates()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var w =new XamlIlBugTestsEventHandlerCodeBehind();
w.ApplyTemplate();
w.Show();
Dispatcher.UIThread.RunJobs();
var itemsPresenter = ((ItemsControl)w.Content).GetVisualChildren().FirstOrDefault();
var item = itemsPresenter
.GetVisualChildren().First()
.GetVisualChildren().First()
.GetVisualChildren().First();
((Control)item).RaiseEvent(new PointerPressedEventArgs {ClickCount = 20});
Assert.Equal(20, w.Args.ClickCount);
}
}
[Fact]
public void Custom_Properties_Should_Work_With_XClass()
{
var precompiled = new XamlIlClassWithCustomProperty();
Assert.Equal("123", precompiled.Test);
var loaded = (XamlIlClassWithCustomProperty)AvaloniaXamlLoader.Parse(@"
<UserControl xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
x:Class='Avalonia.Markup.Xaml.UnitTests.XamlIlClassWithCustomProperty'
Test='321'>
</UserControl>");
Assert.Equal("321", loaded.Test);
}
}
public class XamlIlBugTestsEventHandlerCodeBehind : Window
{
public PointerPressedEventArgs Args;
public void HandlePointerPressed(object sender, PointerPressedEventArgs args)
{
Args = args;
}
public XamlIlBugTestsEventHandlerCodeBehind()
{
new AvaloniaXamlLoader().Load(@"
<Window x:Class='Avalonia.Markup.Xaml.UnitTests.XamlIlBugTestsEventHandlerCodeBehind'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns='https://github.com/avaloniaui'
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests;assembly=Avalonia.Markup.Xaml.UnitTests'
>
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button PointerPressed='HandlePointerPressed' Content='{Binding .}' />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
", typeof(XamlIlBugTestsEventHandlerCodeBehind).Assembly, this);
((ItemsControl)Content).Items = new[] {"123"};
}
}
public class XamlIlClassWithCustomProperty : UserControl
{
public string Test { get; set; }
public XamlIlClassWithCustomProperty()
{
AvaloniaXamlLoader.Load(this);
}
}
public class XamlIlBugTestsBrushToColorConverter : IMultiValueConverter

Loading…
Cancel
Save