Browse Source

Merge branch 'master' into patch-1

pull/9632/head
Steven Kirk 4 years ago
committed by GitHub
parent
commit
1c1025212e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      native/Avalonia.Native/src/OSX/WindowImpl.mm
  2. 15
      samples/IntegrationTestApp/MainWindow.axaml
  3. 3
      samples/IntegrationTestApp/MainWindow.axaml.cs
  4. 8
      samples/IntegrationTestApp/ShowWindowTest.axaml
  5. 67
      src/Avalonia.Base/StyledElement.cs
  6. 3
      src/Avalonia.Base/Styling/StyleInstance.cs
  7. 4
      src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
  8. 2
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  9. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
  10. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
  11. 9
      src/Windows/Avalonia.Win32/TrayIconImpl.cs
  12. 48
      tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs
  13. 51
      tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs
  14. 16
      tests/Avalonia.IntegrationTests.Appium/WindowTests.cs
  15. 74
      tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs
  16. 23
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

9
native/Avalonia.Native/src/OSX/WindowImpl.mm

@ -137,7 +137,11 @@ void WindowImpl::BringToFront()
for(auto iterator = _children.begin(); iterator != _children.end(); iterator++)
{
(*iterator)->BringToFront();
auto window = (*iterator)->Window;
// #9565: Only bring window to front if it's on the currently active space
if ([window isOnActiveSpace])
(*iterator)->BringToFront();
}
}
}
@ -161,6 +165,9 @@ void WindowImpl::StartStateTransition() {
void WindowImpl::EndStateTransition() {
_transitioningWindowState = false;
// Ensure correct order of child windows after fullscreen transition.
BringToFront();
}
SystemDecorations WindowImpl::Decorations() {

15
samples/IntegrationTestApp/MainWindow.axaml

@ -17,11 +17,15 @@
</NativeMenuItem>
<NativeMenuItem Header="View">
<NativeMenu/>
</NativeMenuItem>
</NativeMenuItem>
</NativeMenu>
</NativeMenu.Menu>
<DockPanel>
<NativeMenuBar DockPanel.Dock="Top"/>
<StackPanel DockPanel.Dock="Bottom" Margin="4" Orientation="Horizontal">
<TextBlock Margin="0,0,4,0">WindowState:</TextBlock>
<TextBlock Name="MainWindowState" Text="{Binding WindowState}"/>
</StackPanel>
<TabControl TabStripPlacement="Left" Name="MainTabs">
<TabItem Header="Automation">
@ -129,13 +133,14 @@
<ComboBoxItem>CenterOwner</ComboBoxItem>
</ComboBox>
<ComboBox Name="ShowWindowState" SelectedIndex="0">
<ComboBoxItem>Normal</ComboBoxItem>
<ComboBoxItem>Minimized</ComboBoxItem>
<ComboBoxItem>Maximized</ComboBoxItem>
<ComboBoxItem>FullScreen</ComboBoxItem>
<ComboBoxItem Name="ShowWindowStateNormal">Normal</ComboBoxItem>
<ComboBoxItem Name="ShowWindowStateMinimized">Minimized</ComboBoxItem>
<ComboBoxItem Name="ShowWindowStateMaximized">Maximized</ComboBoxItem>
<ComboBoxItem Name="ShowWindowStateFullScreen">FullScreen</ComboBoxItem>
</ComboBox>
<Button Name="ShowWindow">Show Window</Button>
<Button Name="SendToBack">Send to Back</Button>
<Button Name="EnterFullscreen">Enter Fullscreen</Button>
<Button Name="ExitFullscreen">Exit Fullscreen</Button>
<Button Name="RestoreAll">Restore All</Button>
</StackPanel>

3
samples/IntegrationTestApp/MainWindow.axaml.cs

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia;
@ -178,6 +179,8 @@ namespace IntegrationTestApp
ShowWindow();
if (source?.Name == "SendToBack")
SendToBack();
if (source?.Name == "EnterFullscreen")
WindowState = WindowState.FullScreen;
if (source?.Name == "ExitFullscreen")
WindowState = WindowState.Normal;
if (source?.Name == "RestoreAll")

8
samples/IntegrationTestApp/ShowWindowTest.axaml

@ -27,10 +27,10 @@
<Label Grid.Column="0" Grid.Row="7">WindowState</Label>
<ComboBox Name="WindowState" Grid.Column="1" Grid.Row="7" SelectedIndex="{Binding WindowState}">
<ComboBoxItem>Normal</ComboBoxItem>
<ComboBoxItem>Minimized</ComboBoxItem>
<ComboBoxItem>Maximized</ComboBoxItem>
<ComboBoxItem>FullScreen</ComboBoxItem>
<ComboBoxItem Name="WindowStateNormal">Normal</ComboBoxItem>
<ComboBoxItem Name="WindowStateMinimized">Minimized</ComboBoxItem>
<ComboBoxItem Name="WindowStateMaximized">Maximized</ComboBoxItem>
<ComboBoxItem Name="WindowStateFullScreen">FullScreen</ComboBoxItem>
</ComboBox>
<Label Grid.Column="0" Grid.Row="8">Order (mac)</Label>

67
src/Avalonia.Base/StyledElement.cs

@ -81,6 +81,7 @@ namespace Avalonia
private Styles? _styles;
private bool _stylesApplied;
private bool _themeApplied;
private bool _templatedParentThemeApplied;
private AvaloniaObject? _templatedParent;
private bool _dataContextUpdating;
private ControlTheme? _implicitTheme;
@ -375,6 +376,12 @@ namespace Avalonia
_themeApplied = true;
}
if (!_templatedParentThemeApplied)
{
ApplyTemplatedParentControlTheme();
_templatedParentThemeApplied = true;
}
if (!_stylesApplied)
{
ApplyStyles(this);
@ -613,26 +620,38 @@ namespace Avalonia
base.OnPropertyChanged(change);
if (change.Property == ThemeProperty)
{
OnControlThemeChanged();
_themeApplied = false;
}
}
private protected virtual void OnControlThemeChanged()
{
var values = GetValueStore();
values.BeginStyling();
try { values.RemoveFrames(FrameType.Theme); }
finally { values.EndStyling(); }
try
{
values.RemoveFrames(FrameType.Theme);
}
finally
{
values.EndStyling();
_themeApplied = false;
}
}
internal virtual void OnTemplatedParentControlThemeChanged()
{
var values = GetValueStore();
values.BeginStyling();
try { values.RemoveFrames(FrameType.TemplatedParentTheme); }
finally { values.EndStyling(); }
try
{
values.RemoveFrames(FrameType.TemplatedParentTheme);
}
finally
{
values.EndStyling();
_templatedParentThemeApplied = false;
}
}
internal ControlTheme? GetEffectiveTheme()
@ -743,13 +762,13 @@ namespace Avalonia
private void ApplyControlTheme()
{
var theme = GetEffectiveTheme();
if (theme is not null)
if (GetEffectiveTheme() is { } theme)
ApplyControlTheme(theme, FrameType.Theme);
}
if (TemplatedParent is StyledElement styleableParent &&
styleableParent.GetEffectiveTheme() is { } parentTheme)
private void ApplyTemplatedParentControlTheme()
{
if ((TemplatedParent as StyledElement)?.GetEffectiveTheme() is { } parentTheme)
{
ApplyControlTheme(parentTheme, FrameType.TemplatedParentTheme);
}
@ -793,6 +812,28 @@ namespace Avalonia
ApplyStyle(child, host, type);
}
private void ReevaluateImplicitTheme()
{
// We only need to check if the theme has changed when Theme isn't set (i.e. when we
// have an implicit theme).
if (Theme is not null)
return;
// Refetch the implicit theme.
var oldImplicitTheme = _implicitTheme == s_invalidTheme ? null : _implicitTheme;
_implicitTheme = null;
GetEffectiveTheme();
var newImplicitTheme = _implicitTheme == s_invalidTheme ? null : _implicitTheme;
// If the implicit theme has changed, detach the existing theme.
if (newImplicitTheme != oldImplicitTheme)
{
OnControlThemeChanged();
_themeApplied = false;
}
}
private void OnAttachedToLogicalTreeCore(LogicalTreeAttachmentEventArgs e)
{
if (this.GetLogicalParent() == null && !(this is ILogicalRoot))
@ -811,6 +852,7 @@ namespace Avalonia
{
_logicalRoot = e.Root;
ReevaluateImplicitTheme();
ApplyStyling();
NotifyResourcesChanged(propagate: false);
@ -835,7 +877,6 @@ namespace Avalonia
if (_logicalRoot != null)
{
_logicalRoot = null;
_implicitTheme = null;
InvalidateStyles(recurse: false);
OnDetachedFromLogicalTree(e);
DetachedFromLogicalTree?.Invoke(this, e);

3
src/Avalonia.Base/Styling/StyleInstance.cs

@ -70,6 +70,9 @@ namespace Avalonia.Styling
_animationTrigger ??= new Subject<bool>();
foreach (var animation in _animations)
animation.Apply(animatable, null, _animationTrigger);
if (_activator is null)
_animationTrigger.OnNext(true);
}
}

4
src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml

@ -6,8 +6,8 @@
<StreamGeometry x:Key="DataGridSortIconDescendingPath">M1875 1011l-787 787v-1798h-128v1798l-787 -787l-90 90l941 941l941 -941z</StreamGeometry>
<StreamGeometry x:Key="DataGridSortIconAscendingPath">M1965 947l-941 -941l-941 941l90 90l787 -787v1798h128v-1798l787 787z</StreamGeometry>
<StreamGeometry x:Key="DataGridRowGroupHeaderIconClosedPath">M515 93l930 931l-930 931l90 90l1022 -1021l-1022 -1021z</StreamGeometry>
<StreamGeometry x:Key="DataGridRowGroupHeaderIconOpenedPath">M109 486 19 576 1024 1581 2029 576 1939 486 1024 1401z</StreamGeometry>
<StreamGeometry x:Key="DataGridRowGroupHeaderIconOpenedPath">M515 93l930 931l-930 931l90 90l1022 -1021l-1022 -1021z</StreamGeometry>
<StreamGeometry x:Key="DataGridRowGroupHeaderIconClosedPath">M109 486 19 576 1024 1581 2029 576 1939 486 1024 1401z</StreamGeometry>
<SolidColorBrush x:Key="DataGridColumnHeaderForegroundBrush" Color="{DynamicResource SystemBaseMediumColor}" />
<SolidColorBrush x:Key="DataGridColumnHeaderBackgroundBrush" Color="{DynamicResource SystemAltHighColor}" />

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

@ -588,7 +588,7 @@ namespace Avalonia.Controls.Primitives
}
else if (e.Key == Key.Space || e.Key == Key.Enter)
{
e.Handled = UpdateSelectionFromEventSource(
UpdateSelectionFromEventSource(
e.Source,
true,
e.KeyModifiers.HasFlag(KeyModifiers.Shift),

2
src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs

@ -234,7 +234,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
parsedDocuments.Add(new XamlDocumentResource(parsed, document.BaseUri?.ToString(), null, null,
builder,
compiler.DefinePopulateMethod(builder, parsed, AvaloniaXamlIlCompiler.PopulateName, true),
compiler.DefineBuildMethod(builder, parsed, AvaloniaXamlIlCompiler.BuildName, true)));
document.RootInstance is null ? compiler.DefineBuildMethod(builder, parsed, AvaloniaXamlIlCompiler.BuildName, true) : null));
originalDocuments.Add(document);
}

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

@ -1 +1 @@
Subproject commit 491de981dd4433ee58bc9540e2cd4a5d168f8168
Subproject commit 5e498f8bcca403a34aff5efc825cbb4e12b7fa8e

9
src/Windows/Avalonia.Win32/TrayIconImpl.cs

@ -19,7 +19,6 @@ namespace Avalonia.Win32
public class TrayIconImpl : ITrayIconImpl
{
private static readonly IntPtr s_emptyIcon = new System.Drawing.Bitmap(32, 32).GetHicon();
private readonly int _uniqueId;
private static int s_nextUniqueId;
private bool _iconAdded;
@ -137,6 +136,12 @@ namespace Avalonia.Win32
private void OnRightClicked()
{
var menuItems = _exporter.GetMenu();
if (null == menuItems || menuItems.Count == 0)
{
return;
}
var _trayMenu = new TrayPopupRoot()
{
SystemDecorations = SystemDecorations.None,
@ -145,7 +150,7 @@ namespace Avalonia.Win32
TransparencyLevelHint = WindowTransparencyLevel.Transparent,
Content = new TrayIconMenuFlyoutPresenter()
{
Items = _exporter.GetMenu()
Items = menuItems
}
};

48
tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs

@ -868,7 +868,53 @@ namespace Avalonia.Base.UnitTests.Styling
}
[Fact]
public void Animations_Should_Be_Activated_And_Deactivated()
public void Animations_Should_Be_Activated()
{
Style style = new Style(x => x.OfType<Class1>())
{
Animations =
{
new Avalonia.Animation.Animation
{
Duration = TimeSpan.FromSeconds(1),
Children =
{
new KeyFrame
{
Setters =
{
new Setter { Property = Class1.DoubleProperty, Value = 5.0 }
},
},
new KeyFrame
{
Setters =
{
new Setter { Property = Class1.DoubleProperty, Value = 10.0 }
},
Cue = new Cue(1d)
}
},
}
}
};
var clock = new TestClock();
var target = new Class1 { Clock = clock };
StyleHelpers.TryAttach(style, target);
Assert.Equal(0.0, target.Double);
clock.Step(TimeSpan.Zero);
Assert.Equal(5.0, target.Double);
clock.Step(TimeSpan.FromSeconds(0.5));
Assert.Equal(7.5, target.Double);
}
[Fact]
public void Animations_With_Trigger_Should_Be_Activated_And_Deactivated()
{
Style style = new Style(x => x.OfType<Class1>().Class("foo"))
{

51
tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs

@ -359,16 +359,49 @@ public class StyledElementTests_Theming
}
[Fact]
public void Implicit_Theme_Is_Cleared_When_Removed_From_Logical_Tree()
public void Implicit_Theme_Is_Not_Detached_When_Removed_From_Logical_Tree()
{
var target = CreateTarget();
var root = CreateRoot(target);
Assert.NotNull(target.GetEffectiveTheme());
Assert.Equal("theme", target.Tag);
root.Child = null;
Assert.Null(target.GetEffectiveTheme());
var border = Assert.IsType<Border>(target.VisualChild);
Assert.Equal("theme", target.Tag);
Assert.Equal("theme", border.Tag);
}
[Fact]
public void Can_Attach_Then_Reattach_To_Same_Logical_Tree()
{
var target = CreateTarget();
var root = CreateRoot(target);
Assert.Equal("theme", target.Tag);
root.Child = null;
root.Child = target;
Assert.Equal("theme", target.Tag);
}
[Fact]
public void Implicit_Theme_Is_Reevaluated_When_Removed_And_Added_To_Different_Logical_Tree()
{
var target = CreateTarget();
var root1 = CreateRoot(target, "theme1");
var root2 = CreateRoot(null, "theme2");
Assert.Equal("theme1", target.Tag);
root1.Child = null;
root2.Child = target;
var border = Assert.IsType<Border>(target.VisualChild);
Assert.Equal("theme2", target.Tag);
Assert.Equal("theme2", border.Tag);
}
[Fact]
@ -402,10 +435,10 @@ public class StyledElementTests_Theming
private static ThemedControl CreateTarget() => new ThemedControl();
private static TestRoot CreateRoot(Control child)
private static TestRoot CreateRoot(Control? child, string themeTag = "theme")
{
var result = new TestRoot();
result.Resources.Add(typeof(ThemedControl), CreateTheme());
result.Resources.Add(typeof(ThemedControl), CreateTheme(themeTag));
result.Child = child;
result.LayoutManager.ExecuteInitialLayoutPass();
return result;
@ -530,7 +563,7 @@ public class StyledElementTests_Theming
}
}
private static ControlTheme CreateTheme()
private static ControlTheme CreateTheme(string tag = "theme")
{
var template = new FuncControlTemplate<ThemedControl>((o, n) => new Border());
@ -539,7 +572,7 @@ public class StyledElementTests_Theming
TargetType = typeof(ThemedControl),
Setters =
{
new Setter(Control.TagProperty, "theme"),
new Setter(Control.TagProperty, tag),
new Setter(TemplatedControl.TemplateProperty, template),
new Setter(TemplatedControl.CornerRadiusProperty, new CornerRadius(5)),
},
@ -550,7 +583,7 @@ public class StyledElementTests_Theming
Setters =
{
new Setter(Border.BackgroundProperty, Brushes.Red),
new Setter(Control.TagProperty, "theme"),
new Setter(Control.TagProperty, tag),
}
},
new Style(x => x.Nesting().Class("foo").Template().OfType<Border>())

16
tests/Avalonia.IntegrationTests.Appium/WindowTests.cs

@ -90,7 +90,7 @@ namespace Avalonia.IntegrationTests.Appium
try
{
_session.FindElementByAccessibilityId("WindowState").SendClick();
_session.FindElementByName("Normal").SendClick();
_session.FindElementByAccessibilityId("WindowStateNormal").SendClick();
// Wait for animations to run.
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
@ -155,11 +155,11 @@ namespace Avalonia.IntegrationTests.Appium
Assert.Equal("Normal", windowState.GetComboBoxValue());
windowState.Click();
_session.FindElementByName("Maximized").SendClick();
_session.FindElementByAccessibilityId("WindowStateMaximized").SendClick();
Assert.Equal("Maximized", windowState.GetComboBoxValue());
windowState.Click();
_session.FindElementByName("Normal").SendClick();
_session.FindElementByAccessibilityId("WindowStateNormal").SendClick();
var current = GetWindowInfo();
Assert.Equal(original.Position, current.Position);
@ -169,7 +169,7 @@ namespace Avalonia.IntegrationTests.Appium
if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || mode == ShowWindowMode.NonOwned)
{
windowState.Click();
_session.FindElementByName("FullScreen").SendClick();
_session.FindElementByAccessibilityId("WindowStateFullScreen").SendClick();
Assert.Equal("FullScreen", windowState.GetComboBoxValue());
current = GetWindowInfo();
@ -179,7 +179,7 @@ namespace Avalonia.IntegrationTests.Appium
windowState.SendClick();
_session.FindElementByName("Normal").SendClick();
_session.FindElementByAccessibilityId("WindowStateNormal").SendClick();
current = GetWindowInfo();
Assert.Equal(original.Position, current.Position);
@ -223,13 +223,13 @@ namespace Avalonia.IntegrationTests.Appium
// Not sure how to handle testing minimized windows currently.
if (state == Controls.WindowState.Minimized)
continue;
// Child/Modal windows cannot be fullscreen on macOS.
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) &&
state == Controls.WindowState.FullScreen &&
mode != ShowWindowMode.NonOwned)
continue;
data.Add(size, mode, state);
}
}
@ -286,7 +286,7 @@ namespace Avalonia.IntegrationTests.Appium
_session.FindElementByName(location.ToString()).SendClick();
stateComboBox.Click();
_session.FindElementByName(state.ToString()).SendClick();
_session.FindElementByAccessibilityId($"ShowWindowState{state}").SendClick();
return showButton.OpenWindowWithClick();
}

74
tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Avalonia.Controls;
using Avalonia.Utilities;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Interactions;
@ -114,6 +115,79 @@ namespace Avalonia.IntegrationTests.Appium
Assert.Equal(1, secondaryWindowIndex);
}
}
[PlatformFact(TestPlatforms.MacOS)]
public void WindowOrder_Owned_Dialog_Stays_InFront_Of_FullScreen_Parent()
{
var mainWindow = _session.FindElementByAccessibilityId("MainWindow");
// Enter fullscreen
mainWindow.FindElementByAccessibilityId("EnterFullscreen").Click();
// Wait for fullscreen transition.
Thread.Sleep(1000);
// Make sure we entered fullscreen.
var windowState = mainWindow.FindElementByAccessibilityId("MainWindowState");
Assert.Equal("FullScreen", windowState.Text);
// Open child window.
using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual))
{
mainWindow.SendClick();
var secondaryWindowIndex = GetWindowOrder("SecondaryWindow");
Assert.Equal(1, secondaryWindowIndex);
}
// Exit fullscreen by menu shortcut Command+R
mainWindow.FindElementByAccessibilityId("ExitFullscreen").Click();
// Wait for restore transition.
Thread.Sleep(1000);
// Make sure we exited fullscreen.
mainWindow = _session.FindElementByAccessibilityId("MainWindow");
windowState = mainWindow.FindElementByAccessibilityId("MainWindowState");
Assert.Equal("Normal", windowState.Text);
}
[PlatformFact(TestPlatforms.MacOS)]
public void Does_Not_Switch_Space_From_FullScreen_To_Main_Desktop_When_FullScreen_Window_Clicked()
{
// Issue #9565
var mainWindow = _session.FindElementByAccessibilityId("MainWindow");
AppiumWebElement windowState;
// Open child window.
using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual))
{
// Enter fullscreen
mainWindow.FindElementByAccessibilityId("EnterFullscreen").Click();
// Wait for fullscreen transition.
Thread.Sleep(1000);
// Make sure we entered fullscreen.
mainWindow = _session.FindElementByAccessibilityId("MainWindow");
windowState = mainWindow.FindElementByAccessibilityId("MainWindowState");
Assert.Equal("FullScreen", windowState.Text);
// Click on main window
mainWindow.Click();
// Failed here due to #9565: main window is no longer visible as the main space is now shown instead
// of the fullscreen space.
mainWindow.FindElementByAccessibilityId("ExitFullscreen").Click();
// Wait for restore transition.
Thread.Sleep(1000);
}
// Make sure we exited fullscreen.
mainWindow = _session.FindElementByAccessibilityId("MainWindow");
windowState = mainWindow.FindElementByAccessibilityId("MainWindowState");
Assert.Equal("Normal", windowState.Text);
}
[PlatformFact(TestPlatforms.MacOS)]
public void WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent()

23
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

@ -899,6 +899,17 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.Equal("Foo", target.Text);
}
[Fact]
public void Should_Parse_And_Populate_Type_Without_Public_Ctor()
{
var xaml = @"<ObjectWithoutPublicCtor xmlns='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml' Test2='World' />";
var target = (ObjectWithoutPublicCtor)AvaloniaRuntimeXamlLoader.Load(xaml, rootInstance: new ObjectWithoutPublicCtor("Hello"));
Assert.NotNull(target);
Assert.Equal("World", target.Test2);
Assert.Equal("Hello", target.Test1);
}
private class SelectedItemsViewModel : INotifyPropertyChanged
{
public string[] Items { get; set; }
@ -928,6 +939,18 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Child = child;
}
}
public class ObjectWithoutPublicCtor
{
public ObjectWithoutPublicCtor(string param)
{
Test1 = param;
}
public string Test1 { get; set; }
public string Test2 { get; set; }
}
public class ObjectWithAddChildOfT : IAddChild, IAddChild<string>
{

Loading…
Cancel
Save