Browse Source

Don't allow binding to `ItemsControl.Items`.

Depends on https://github.com/kekekeks/XamlX/pull/85: this PR disallows invoking "collection behavior" for property setters when using attribute syntax.

Required adding a `Flyout.FlyoutPresenterClasses` setter. This property was previously buggy without the setter (see https://github.com/AvaloniaUI/Avalonia/issues/10946#issuecomment-1506563268). Added tests for setting classes that I put in place when investigating this.

Fixes #10946
pull/11008/head
Steven Kirk 3 years ago
parent
commit
1a3b8fbcac
  1. 16
      src/Avalonia.Controls/Flyouts/Flyout.cs
  2. 3
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDeferredResourceTransformer.cs
  3. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDesignPropertiesTransformer.cs
  4. 3
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/XDataTypeTransformer.cs
  5. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/XNameTransformer.cs
  6. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
  7. 4
      src/tools/Avalonia.Generators/Compiler/NameDirectiveTransformer.cs
  8. 28
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

16
src/Avalonia.Controls/Flyouts/Flyout.cs

@ -13,12 +13,22 @@ namespace Avalonia.Controls
public static readonly StyledProperty<object> ContentProperty =
AvaloniaProperty.Register<Flyout, object>(nameof(Content));
private Classes? _classes;
/// <summary>
/// Gets the Classes collection to apply to the FlyoutPresenter this Flyout is hosting
/// </summary>
public Classes FlyoutPresenterClasses => _classes ??= new Classes();
private Classes? _classes;
public Classes FlyoutPresenterClasses
{
get => _classes ??= new Classes();
set
{
if (_classes is null)
_classes = value;
else if (_classes != value)
_classes.Replace(value);
}
}
/// <summary>
/// Defines the <see cref="FlyoutPresenterTheme"/> property.

3
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDeferredResourceTransformer.cs

@ -65,7 +65,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
AllowMultiple = true,
AllowXNull = allowNull,
AllowRuntimeNull = allowNull
AllowRuntimeNull = allowNull,
AllowAttributeSyntax = false,
};
}

2
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDesignPropertiesTransformer.cs

@ -37,7 +37,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
on.Children[c] = new XamlAstXamlPropertyValueNode(ch,
new XamlAstNamePropertyReference(ch,
new XamlAstXmlTypeReference(ch, AvaloniaNs, "Design"),
mapTo, on.Type), directive.Values);
mapTo, on.Type), directive.Values, true);
c++;
}
}

3
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/XDataTypeTransformer.cs

@ -52,7 +52,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
new XamlAstNamePropertyReference(d,
new XamlAstClrTypeReference(ch, declaringType, false), dataTypeProperty.Name,
on.Type),
d.Values);
d.Values,
true);
}
}
}

2
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/XNameTransformer.cs

@ -24,7 +24,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
on.Children[c] = new XamlAstXamlPropertyValueNode(d,
new XamlAstNamePropertyReference(d, on.Type, "Name", on.Type),
d.Values);
d.Values, true);
}
}

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

@ -1 +1 @@
Subproject commit 5e498f8bcca403a34aff5efc825cbb4e12b7fa8e
Subproject commit 5dd0b042e144e677638224c49fec16dab66143e8

4
src/tools/Avalonia.Generators/Compiler/NameDirectiveTransformer.cs

@ -20,9 +20,9 @@ internal class NameDirectiveTransformer : IXamlAstTransformer
objectNode.Children[index] = new XamlAstXamlPropertyValueNode(
directive,
new XamlAstNamePropertyReference(directive, objectNode.Type, "Name", objectNode.Type),
directive.Values);
directive.Values, true);
}
return node;
}
}
}

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

@ -910,7 +910,33 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.Equal("World", target.Test2);
Assert.Equal("Hello", target.Test1);
}
[Fact]
public void Can_Specify_Button_Classes()
{
var xaml = "<Button xmlns='https://github.com/avaloniaui' Classes='foo bar'/>";
var target = (Button)AvaloniaRuntimeXamlLoader.Load(xaml);
Assert.Equal(new[] { "foo", "bar" }, target.Classes);
}
[Fact]
public void Can_Specify_Flyout_FlyoutPresenterClasses()
{
var xaml = "<Flyout xmlns='https://github.com/avaloniaui' FlyoutPresenterClasses='foo bar'/>";
var target = (Flyout)AvaloniaRuntimeXamlLoader.Load(xaml);
Assert.Equal(new[] { "foo", "bar" }, target.FlyoutPresenterClasses);
}
[Fact]
public void Trying_To_Bind_ItemsControl_Items_Throws()
{
var xaml = "<ItemsControl xmlns='https://github.com/avaloniaui' Items='{Binding}'/>";
Assert.ThrowsAny<XmlException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
}
private class SelectedItemsViewModel : INotifyPropertyChanged
{
public string[] Items { get; set; }

Loading…
Cancel
Save