committed by
GitHub
41 changed files with 701 additions and 310 deletions
@ -0,0 +1,17 @@ |
|||||
|
This template is not intended to be prescriptive, but to help us review pull requests it would be useful if you included as much of the following information as possible: |
||||
|
|
||||
|
- What does the pull request do? |
||||
|
- What is the current behavior? |
||||
|
- What is the updated/expected behavior with this PR? |
||||
|
- How was the solution implemented (if it's not obvious)? |
||||
|
|
||||
|
Checklist: |
||||
|
|
||||
|
- [ ] Added unit tests (if possible)? |
||||
|
- [ ] Added XML documentation to any related classes? |
||||
|
- [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Avaloniaui.net with user documentation |
||||
|
|
||||
|
If the pull request fixes issue(s) list them like this: |
||||
|
|
||||
|
Fixes #123 |
||||
|
Fixes #456 |
||||
@ -1,6 +1,6 @@ |
|||||
<Window xmlns="https://github.com/avaloniaui" MinWidth="500" MinHeight="300" |
<Window xmlns="https://github.com/avaloniaui" MinWidth="500" MinHeight="300" |
||||
Title="Avalonia Control Gallery" |
Title="Avalonia Control Gallery" |
||||
Icon="resm:ControlCatalog.Assets.test_icon.ico?assembly=ControlCatalog" |
Icon="resm:ControlCatalog.Assets.test_icon.ico?assembly=ControlCatalog" |
||||
xmlns:local="clr-namespace:ControlCatalog;assembly=ControlCatalog"> |
xmlns:local="clr-namespace:ControlCatalog"> |
||||
<local:MainView/> |
<local:MainView/> |
||||
</Window> |
</Window> |
||||
@ -1,11 +1,237 @@ |
|||||
namespace Avalonia.Markup.Xaml |
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Markup.Xaml.Data; |
||||
|
using Avalonia.Markup.Xaml.PortableXaml; |
||||
|
using Avalonia.Platform; |
||||
|
using Portable.Xaml; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.IO; |
||||
|
using System.Reflection; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace Avalonia.Markup.Xaml |
||||
{ |
{ |
||||
public class AvaloniaXamlLoader : AvaloniaXamlLoaderPortableXaml |
/// <summary>
|
||||
|
/// Loads XAML for a avalonia application.
|
||||
|
/// </summary>
|
||||
|
public class AvaloniaXamlLoader |
||||
{ |
{ |
||||
public static object Parse(string xaml) |
private readonly AvaloniaXamlSchemaContext _context = GetContext(); |
||||
=> new AvaloniaXamlLoader().Load(xaml); |
|
||||
|
private static AvaloniaXamlSchemaContext GetContext() |
||||
|
{ |
||||
|
var result = AvaloniaLocator.Current.GetService<AvaloniaXamlSchemaContext>(); |
||||
|
|
||||
|
if (result == null) |
||||
|
{ |
||||
|
result = AvaloniaXamlSchemaContext.Create(); |
||||
|
|
||||
|
AvaloniaLocator.CurrentMutable |
||||
|
.Bind<AvaloniaXamlSchemaContext>() |
||||
|
.ToConstant(result); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> class.
|
||||
|
/// </summary>
|
||||
|
public AvaloniaXamlLoader() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads the XAML into a Avalonia component.
|
||||
|
/// </summary>
|
||||
|
/// <param name="obj">The object to load the XAML into.</param>
|
||||
|
public static void Load(object obj) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(obj != null); |
||||
|
|
||||
|
var loader = new AvaloniaXamlLoader(); |
||||
|
loader.Load(obj.GetType(), obj); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads the XAML for a type.
|
||||
|
/// </summary>
|
||||
|
/// <param name="type">The type.</param>
|
||||
|
/// <param name="rootInstance">
|
||||
|
/// The optional instance into which the XAML should be loaded.
|
||||
|
/// </param>
|
||||
|
/// <returns>The loaded object.</returns>
|
||||
|
public object Load(Type type, object rootInstance = null) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(type != null); |
||||
|
|
||||
|
// HACK: Currently Visual Studio is forcing us to change the extension of xaml files
|
||||
|
// in certain situations, so we try to load .xaml and if that's not found we try .xaml.
|
||||
|
// Ideally we'd be able to use .xaml everywhere
|
||||
|
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>(); |
||||
|
|
||||
|
if (assetLocator == null) |
||||
|
{ |
||||
|
throw new InvalidOperationException( |
||||
|
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?"); |
||||
|
} |
||||
|
|
||||
|
foreach (var uri in GetUrisFor(type)) |
||||
|
{ |
||||
|
if (assetLocator.Exists(uri)) |
||||
|
{ |
||||
|
using (var stream = assetLocator.Open(uri)) |
||||
|
{ |
||||
|
var initialize = rootInstance as ISupportInitialize; |
||||
|
initialize?.BeginInit(); |
||||
|
try |
||||
|
{ |
||||
|
return Load(stream, type.Assembly, rootInstance, uri); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
initialize?.EndInit(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
throw new FileNotFoundException("Unable to find view for " + type.FullName); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads XAML from a URI.
|
||||
|
/// </summary>
|
||||
|
/// <param name="uri">The URI of the XAML file.</param>
|
||||
|
/// <param name="baseUri">
|
||||
|
/// A base URI to use if <paramref name="uri"/> is relative.
|
||||
|
/// </param>
|
||||
|
/// <param name="rootInstance">
|
||||
|
/// The optional instance into which the XAML should be loaded.
|
||||
|
/// </param>
|
||||
|
/// <returns>The loaded object.</returns>
|
||||
|
public object Load(Uri uri, Uri baseUri = null, object rootInstance = null) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(uri != null); |
||||
|
|
||||
|
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>(); |
||||
|
|
||||
|
if (assetLocator == null) |
||||
|
{ |
||||
|
throw new InvalidOperationException( |
||||
|
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?"); |
||||
|
} |
||||
|
|
||||
|
var asset = assetLocator.OpenAndGetAssembly(uri, baseUri); |
||||
|
using (var stream = asset.Item1) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
return Load(stream, asset.Item2, rootInstance, uri); |
||||
|
} |
||||
|
catch (Exception e) |
||||
|
{ |
||||
|
var uriString = uri.ToString(); |
||||
|
if (!uri.IsAbsoluteUri) |
||||
|
{ |
||||
|
uriString = new Uri(baseUri, uri).AbsoluteUri; |
||||
|
} |
||||
|
throw new XamlLoadException("Error loading xaml at " + uriString, e); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads XAML from a string.
|
||||
|
/// </summary>
|
||||
|
/// <param name="xaml">The string containing the XAML.</param>
|
||||
|
/// <param name="localAssembly">Default assembly for clr-namespace:</param>
|
||||
|
/// <param name="rootInstance">
|
||||
|
/// The optional instance into which the XAML should be loaded.
|
||||
|
/// </param>
|
||||
|
/// <returns>The loaded object.</returns>
|
||||
|
public object Load(string xaml, Assembly localAssembly = null, object rootInstance = null) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(xaml != null); |
||||
|
|
||||
|
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml))) |
||||
|
{ |
||||
|
return Load(stream, localAssembly, rootInstance); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads XAML from a stream.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The stream containing the XAML.</param>
|
||||
|
/// <param name="localAssembly">Default assembly for clr-namespace</param>
|
||||
|
/// <param name="rootInstance">
|
||||
|
/// The optional instance into which the XAML should be loaded.
|
||||
|
/// </param>
|
||||
|
/// <param name="uri">The URI of the XAML</param>
|
||||
|
/// <returns>The loaded object.</returns>
|
||||
|
public object Load(Stream stream, Assembly localAssembly, object rootInstance = null, Uri uri = null) |
||||
|
{ |
||||
|
var readerSettings = new XamlXmlReaderSettings() |
||||
|
{ |
||||
|
BaseUri = uri, |
||||
|
LocalAssembly = localAssembly |
||||
|
}; |
||||
|
|
||||
|
var reader = new XamlXmlReader(stream, _context, readerSettings); |
||||
|
|
||||
|
object result = LoadFromReader( |
||||
|
reader, |
||||
|
AvaloniaXamlContext.For(readerSettings, rootInstance)); |
||||
|
|
||||
|
var topLevel = result as TopLevel; |
||||
|
|
||||
|
if (topLevel != null) |
||||
|
{ |
||||
|
DelayedBinding.ApplyBindings(topLevel); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
internal static object LoadFromReader(XamlReader reader, AvaloniaXamlContext context = null, IAmbientProvider parentAmbientProvider = null) |
||||
|
{ |
||||
|
var writer = AvaloniaXamlObjectWriter.Create( |
||||
|
reader.SchemaContext, |
||||
|
context, |
||||
|
parentAmbientProvider); |
||||
|
|
||||
|
XamlServices.Transform(reader, writer); |
||||
|
writer.ApplyAllDelayedProperties(); |
||||
|
return writer.Result; |
||||
|
} |
||||
|
|
||||
|
internal static object LoadFromReader(XamlReader reader) |
||||
|
{ |
||||
|
//return XamlServices.Load(reader);
|
||||
|
return LoadFromReader(reader, null); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the URI for a type.
|
||||
|
/// </summary>
|
||||
|
/// <param name="type">The type.</param>
|
||||
|
/// <returns>The URI.</returns>
|
||||
|
private static IEnumerable<Uri> GetUrisFor(Type type) |
||||
|
{ |
||||
|
var asm = type.GetTypeInfo().Assembly.GetName().Name; |
||||
|
var typeName = type.FullName; |
||||
|
yield return new Uri("resm:" + typeName + ".xaml?assembly=" + asm); |
||||
|
yield return new Uri("resm:" + typeName + ".paml?assembly=" + asm); |
||||
|
} |
||||
|
|
||||
|
public static object Parse(string xaml, Assembly localAssembly = null) |
||||
|
=> new AvaloniaXamlLoader().Load(xaml, localAssembly); |
||||
|
|
||||
public static T Parse<T>(string xaml) |
public static T Parse<T>(string xaml, Assembly localAssembly = null) |
||||
=> (T)Parse(xaml); |
=> (T)Parse(xaml, localAssembly); |
||||
} |
} |
||||
} |
} |
||||
@ -1,227 +0,0 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
using Avalonia.Controls; |
|
||||
using Avalonia.Markup.Xaml.Data; |
|
||||
using Avalonia.Markup.Xaml.PortableXaml; |
|
||||
using Avalonia.Platform; |
|
||||
using Portable.Xaml; |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.IO; |
|
||||
using System.Reflection; |
|
||||
using System.Text; |
|
||||
|
|
||||
namespace Avalonia.Markup.Xaml |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Loads XAML for a avalonia application.
|
|
||||
/// </summary>
|
|
||||
public class AvaloniaXamlLoaderPortableXaml |
|
||||
{ |
|
||||
private readonly AvaloniaXamlSchemaContext _context = GetContext(); |
|
||||
|
|
||||
private static AvaloniaXamlSchemaContext GetContext() |
|
||||
{ |
|
||||
var result = AvaloniaLocator.Current.GetService<AvaloniaXamlSchemaContext>(); |
|
||||
|
|
||||
if (result == null) |
|
||||
{ |
|
||||
result = AvaloniaXamlSchemaContext.Create(); |
|
||||
|
|
||||
AvaloniaLocator.CurrentMutable |
|
||||
.Bind<AvaloniaXamlSchemaContext>() |
|
||||
.ToConstant(result); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> class.
|
|
||||
/// </summary>
|
|
||||
public AvaloniaXamlLoaderPortableXaml() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Loads the XAML into a Avalonia component.
|
|
||||
/// </summary>
|
|
||||
/// <param name="obj">The object to load the XAML into.</param>
|
|
||||
public static void Load(object obj) |
|
||||
{ |
|
||||
Contract.Requires<ArgumentNullException>(obj != null); |
|
||||
|
|
||||
var loader = new AvaloniaXamlLoader(); |
|
||||
loader.Load(obj.GetType(), obj); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Loads the XAML for a type.
|
|
||||
/// </summary>
|
|
||||
/// <param name="type">The type.</param>
|
|
||||
/// <param name="rootInstance">
|
|
||||
/// The optional instance into which the XAML should be loaded.
|
|
||||
/// </param>
|
|
||||
/// <returns>The loaded object.</returns>
|
|
||||
public object Load(Type type, object rootInstance = null) |
|
||||
{ |
|
||||
Contract.Requires<ArgumentNullException>(type != null); |
|
||||
|
|
||||
// HACK: Currently Visual Studio is forcing us to change the extension of xaml files
|
|
||||
// in certain situations, so we try to load .xaml and if that's not found we try .xaml.
|
|
||||
// Ideally we'd be able to use .xaml everywhere
|
|
||||
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>(); |
|
||||
|
|
||||
if (assetLocator == null) |
|
||||
{ |
|
||||
throw new InvalidOperationException( |
|
||||
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?"); |
|
||||
} |
|
||||
|
|
||||
foreach (var uri in GetUrisFor(type)) |
|
||||
{ |
|
||||
if (assetLocator.Exists(uri)) |
|
||||
{ |
|
||||
using (var stream = assetLocator.Open(uri)) |
|
||||
{ |
|
||||
var initialize = rootInstance as ISupportInitialize; |
|
||||
initialize?.BeginInit(); |
|
||||
try |
|
||||
{ |
|
||||
return Load(stream, rootInstance, uri); |
|
||||
} |
|
||||
finally |
|
||||
{ |
|
||||
initialize?.EndInit(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
throw new FileNotFoundException("Unable to find view for " + type.FullName); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Loads XAML from a URI.
|
|
||||
/// </summary>
|
|
||||
/// <param name="uri">The URI of the XAML file.</param>
|
|
||||
/// <param name="baseUri">
|
|
||||
/// A base URI to use if <paramref name="uri"/> is relative.
|
|
||||
/// </param>
|
|
||||
/// <param name="rootInstance">
|
|
||||
/// The optional instance into which the XAML should be loaded.
|
|
||||
/// </param>
|
|
||||
/// <returns>The loaded object.</returns>
|
|
||||
public object Load(Uri uri, Uri baseUri = null, object rootInstance = null) |
|
||||
{ |
|
||||
Contract.Requires<ArgumentNullException>(uri != null); |
|
||||
|
|
||||
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>(); |
|
||||
|
|
||||
if (assetLocator == null) |
|
||||
{ |
|
||||
throw new InvalidOperationException( |
|
||||
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?"); |
|
||||
} |
|
||||
|
|
||||
using (var stream = assetLocator.Open(uri, baseUri)) |
|
||||
{ |
|
||||
try |
|
||||
{ |
|
||||
return Load(stream, rootInstance, uri); |
|
||||
} |
|
||||
catch (Exception e) |
|
||||
{ |
|
||||
var uriString = uri.ToString(); |
|
||||
if (!uri.IsAbsoluteUri) |
|
||||
{ |
|
||||
uriString = new Uri(baseUri, uri).AbsoluteUri; |
|
||||
} |
|
||||
throw new XamlLoadException("Error loading xaml at " + uriString, e); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Loads XAML from a string.
|
|
||||
/// </summary>
|
|
||||
/// <param name="xaml">The string containing the XAML.</param>
|
|
||||
/// <param name="rootInstance">
|
|
||||
/// The optional instance into which the XAML should be loaded.
|
|
||||
/// </param>
|
|
||||
/// <returns>The loaded object.</returns>
|
|
||||
public object Load(string xaml, object rootInstance = null) |
|
||||
{ |
|
||||
Contract.Requires<ArgumentNullException>(xaml != null); |
|
||||
|
|
||||
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml))) |
|
||||
{ |
|
||||
return Load(stream, rootInstance); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Loads XAML from a stream.
|
|
||||
/// </summary>
|
|
||||
/// <param name="stream">The stream containing the XAML.</param>
|
|
||||
/// <param name="rootInstance">
|
|
||||
/// The optional instance into which the XAML should be loaded.
|
|
||||
/// </param>
|
|
||||
/// <param name="uri">The URI of the XAML</param>
|
|
||||
/// <returns>The loaded object.</returns>
|
|
||||
public object Load(Stream stream, object rootInstance = null, Uri uri = null) |
|
||||
{ |
|
||||
var readerSettings = new XamlXmlReaderSettings() |
|
||||
{ |
|
||||
BaseUri = uri, |
|
||||
LocalAssembly = rootInstance?.GetType().GetTypeInfo().Assembly |
|
||||
}; |
|
||||
|
|
||||
var reader = new XamlXmlReader(stream, _context, readerSettings); |
|
||||
|
|
||||
object result = LoadFromReader( |
|
||||
reader, |
|
||||
AvaloniaXamlContext.For(readerSettings, rootInstance)); |
|
||||
|
|
||||
var topLevel = result as TopLevel; |
|
||||
|
|
||||
if (topLevel != null) |
|
||||
{ |
|
||||
DelayedBinding.ApplyBindings(topLevel); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
internal static object LoadFromReader(XamlReader reader, AvaloniaXamlContext context = null) |
|
||||
{ |
|
||||
var writer = AvaloniaXamlObjectWriter.Create( |
|
||||
reader.SchemaContext, |
|
||||
context); |
|
||||
|
|
||||
XamlServices.Transform(reader, writer); |
|
||||
writer.ApplyAllDelayedProperties(); |
|
||||
return writer.Result; |
|
||||
} |
|
||||
|
|
||||
internal static object LoadFromReader(XamlReader reader) |
|
||||
{ |
|
||||
//return XamlServices.Load(reader);
|
|
||||
return LoadFromReader(reader, null); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the URI for a type.
|
|
||||
/// </summary>
|
|
||||
/// <param name="type">The type.</param>
|
|
||||
/// <returns>The URI.</returns>
|
|
||||
private static IEnumerable<Uri> GetUrisFor(Type type) |
|
||||
{ |
|
||||
var asm = type.GetTypeInfo().Assembly.GetName().Name; |
|
||||
var typeName = type.FullName; |
|
||||
yield return new Uri("resm:" + typeName + ".xaml?assembly=" + asm); |
|
||||
yield return new Uri("resm:" + typeName + ".paml?assembly=" + asm); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1 +1 @@ |
|||||
Subproject commit c0664014455392ac221a765e66f9837704339b6f |
Subproject commit faa952f3a05b4bdf2986d686f4154b1ab084508a |
||||
@ -0,0 +1,71 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Controls.Presenters; |
||||
|
using Avalonia.Controls.Templates; |
||||
|
using Avalonia.Styling; |
||||
|
using Avalonia.UnitTests; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions |
||||
|
{ |
||||
|
public class BindingExtensionTests |
||||
|
{ |
||||
|
|
||||
|
[Fact] |
||||
|
public void BindingExtension_Binds_To_Source() |
||||
|
{ |
||||
|
using (StyledWindow()) |
||||
|
{ |
||||
|
var xaml = @"
|
||||
|
<Window xmlns='https://github.com/avaloniaui'
|
||||
|
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
|
||||
|
<Window.Resources> |
||||
|
<x:String x:Key='text'>foobar</x:String> |
||||
|
</Window.Resources> |
||||
|
|
||||
|
<TextBlock Name='textBlock' Text='{Binding Source={StaticResource text}}'/> |
||||
|
</Window>";
|
||||
|
|
||||
|
var loader = new AvaloniaXamlLoader(); |
||||
|
var window = (Window)loader.Load(xaml); |
||||
|
var textBlock = window.FindControl<TextBlock>("textBlock"); |
||||
|
|
||||
|
window.Show(); |
||||
|
|
||||
|
Assert.Equal("foobar", textBlock.Text); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private IDisposable StyledWindow(params (string, string)[] assets) |
||||
|
{ |
||||
|
var services = TestServices.StyledWindow.With( |
||||
|
assetLoader: new MockAssetLoader(assets), |
||||
|
theme: () => new Styles |
||||
|
{ |
||||
|
WindowStyle(), |
||||
|
}); |
||||
|
|
||||
|
return UnitTestApplication.Start(services); |
||||
|
} |
||||
|
|
||||
|
private Style WindowStyle() |
||||
|
{ |
||||
|
return new Style(x => x.OfType<Window>()) |
||||
|
{ |
||||
|
Setters = |
||||
|
{ |
||||
|
new Setter( |
||||
|
Window.TemplateProperty, |
||||
|
new FuncControlTemplate<Window>(x => |
||||
|
new ContentPresenter |
||||
|
{ |
||||
|
Name = "PART_ContentPresenter", |
||||
|
[!ContentPresenter.ContentProperty] = x[!Window.ContentProperty], |
||||
|
})) |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue