Browse Source

Support for mc:Ignorable + d:DataContext

pull/1952/head
Nikita Tsukanov 7 years ago
parent
commit
04228b6d03
  1. 2
      src/Avalonia.DesignerSupport/DesignWindowLoader.cs
  2. 10
      src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
  3. 37
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlObjectWriter.cs
  4. 18
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs
  5. 41
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

2
src/Avalonia.DesignerSupport/DesignWindowLoader.cs

@ -18,7 +18,7 @@ namespace Avalonia.DesignerSupport
Control control;
using (PlatformManager.DesignerMode())
{
var loader = new AvaloniaXamlLoader();
var loader = new AvaloniaXamlLoader() {IsDesignMode = true};
var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml));

10
src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs

@ -21,6 +21,12 @@ namespace Avalonia.Markup.Xaml
{
private readonly AvaloniaXamlSchemaContext _context = GetContext();
public bool IsDesignMode
{
get => _context.IsDesignMode;
set => _context.IsDesignMode = value;
}
private static AvaloniaXamlSchemaContext GetContext()
{
var result = AvaloniaLocator.Current.GetService<AvaloniaXamlSchemaContext>();
@ -200,7 +206,7 @@ namespace Avalonia.Markup.Xaml
internal static object LoadFromReader(XamlReader reader, AvaloniaXamlContext context = null, IAmbientProvider parentAmbientProvider = null)
{
var writer = AvaloniaXamlObjectWriter.Create(
reader.SchemaContext,
(AvaloniaXamlSchemaContext)reader.SchemaContext,
context,
parentAmbientProvider);
@ -234,4 +240,4 @@ namespace Avalonia.Markup.Xaml
public static T Parse<T>(string xaml, Assembly localAssembly = null)
=> (T)Parse(xaml, localAssembly);
}
}
}

37
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlObjectWriter.cs

@ -4,13 +4,27 @@ using Portable.Xaml.ComponentModel;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Avalonia.Controls;
using Portable.Xaml.Schema;
namespace Avalonia.Markup.Xaml.PortableXaml
{
public class AvaloniaXamlObjectWriter : XamlObjectWriter
class AvaloniaXamlObjectWriter : XamlObjectWriter
{
private static Dictionary<XamlDirective, string> DesignDirectives = new Dictionary<string, string>
{
["DataContext"] = "DataContext",
["DesignWidth"] = "Width", ["DesignHeight"] = "Height", ["PreviewWith"] = "PreviewWith"
}
.ToDictionary(p => new XamlDirective(
new[] {"http://schemas.microsoft.com/expression/blend/2008"}, p.Key,
XamlLanguage.Object, null, AllowedMemberLocations.Attribute), p => p.Value);
private readonly AvaloniaXamlSchemaContext _schemaContext;
public static AvaloniaXamlObjectWriter Create(
XamlSchemaContext schemaContext,
AvaloniaXamlSchemaContext schemaContext,
AvaloniaXamlContext context,
IAmbientProvider parentAmbientProvider = null)
{
@ -34,13 +48,14 @@ namespace Avalonia.Markup.Xaml.PortableXaml
private AvaloniaNameScope _nameScope;
private AvaloniaXamlObjectWriter(
XamlSchemaContext schemaContext,
AvaloniaXamlSchemaContext schemaContext,
XamlObjectWriterSettings settings,
AvaloniaNameScope nameScope,
IAmbientProvider parentAmbientProvider)
: base(schemaContext, settings, parentAmbientProvider)
{
_nameScope = nameScope;
_schemaContext = schemaContext;
}
protected override void Dispose(bool disposing)
@ -122,6 +137,20 @@ namespace Avalonia.Markup.Xaml.PortableXaml
(value as Avalonia.ISupportInitialize)?.EndInit();
}
public override void WriteStartMember(XamlMember property)
{
foreach(var d in DesignDirectives)
if (property == d.Key && _schemaContext.IsDesignMode)
{
base.WriteStartMember(new XamlMember(d.Value,
typeof(Design).GetMethod("Get" + d.Value, BindingFlags.Static | BindingFlags.Public),
typeof(Design).GetMethod("Set" + d.Value, BindingFlags.Static | BindingFlags.Public),
SchemaContext));
return;
}
base.WriteStartMember(property);
}
private class DelayedValuesHelper
{
private int _cnt;
@ -225,4 +254,4 @@ namespace Avalonia.Markup.Xaml.PortableXaml
}
}
}
}
}

18
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs

@ -15,6 +15,7 @@ namespace Avalonia.Markup.Xaml.PortableXaml
{
internal class AvaloniaXamlSchemaContext : XamlSchemaContext
{
public bool IsDesignMode { get; set; }
public static AvaloniaXamlSchemaContext Create(IRuntimeTypeProvider typeProvider = null)
{
return new AvaloniaXamlSchemaContext(typeProvider ?? new AvaloniaRuntimeTypeProvider());
@ -280,5 +281,20 @@ namespace Avalonia.Markup.Xaml.PortableXaml
return $"{MemberType}:{Type.Namespace}:{Type.Name}.{Member}";
}
}
public override bool TryGetCompatibleXamlNamespace(string xamlNamespace, out string compatibleNamespace)
{
//Forces XamlXmlReader to not ignore our namespace in design mode if mc:Ignorable is set
if (IsDesignMode &&
xamlNamespace == "http://schemas.microsoft.com/expression/blend/2008")
{
compatibleNamespace = xamlNamespace;
return true;
}
return base.TryGetCompatibleXamlNamespace(xamlNamespace, out compatibleNamespace);
}
}
}
}

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

@ -924,6 +924,45 @@ do we need it?")]
}
}
[Fact]
public void Design_Mode_Properties_Should_Be_Ignored_At_Runtime_And_Set_In_Design_Mode()
{
using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:d='http://schemas.microsoft.com/expression/blend/2008'
xmlns:mc='http://schemas.openxmlformats.org/markup-compatibility/2006'
mc:Ignorable='d'
d:DataContext='data-context'
d:DesignWidth='123'
d:DesignHeight='321'
>
</Window>";
foreach (var designMode in new[] {true, false})
{
var loader = new AvaloniaXamlLoader {IsDesignMode = designMode};
var obj = (Window)loader.Load(xaml);
var context = Design.GetDataContext(obj);
var width = Design.GetWidth(obj);
var height = Design.GetHeight(obj);
if (designMode)
{
Assert.Equal("data-context", context);
Assert.Equal(123, width);
Assert.Equal(321, height);
}
else
{
Assert.False(obj.IsSet(Design.DataContextProperty));
Assert.False(obj.IsSet(Design.WidthProperty));
Assert.False(obj.IsSet(Design.HeightProperty));
}
}
}
}
private class SelectedItemsViewModel : INotifyPropertyChanged
{
public string[] Items { get; set; }
@ -952,4 +991,4 @@ do we need it?")]
public static string GetFoo(AvaloniaObject target) => (string)target.GetValue(FooProperty);
}
}
}

Loading…
Cancel
Save