diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index ef253a28e2..516da813ef 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -17,7 +17,9 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Logging;
using Avalonia.LogicalTree;
+using Avalonia.Rendering;
using Avalonia.Styling;
+using Avalonia.VisualTree;
namespace Avalonia.Controls
{
@@ -33,7 +35,7 @@ namespace Avalonia.Controls
/// - Implements to allow styling to work on the control.
/// - Implements to form part of a logical tree.
///
- public class Control : InputElement, IControl, INamed, ISetInheritanceParent, ISetLogicalParent, ISupportInitialize
+ public class Control : InputElement, IControl, INamed, ISetInheritanceParent, ISetLogicalParent, ISupportInitialize, IVisualBrushInitialize
{
///
/// Defines the property.
@@ -460,6 +462,38 @@ namespace Avalonia.Controls
InheritanceParent = parent;
}
+ ///
+ void IVisualBrushInitialize.EnsureInitialized()
+ {
+ if (VisualRoot == null)
+ {
+ if (!IsInitialized)
+ {
+ foreach (var i in this.GetSelfAndVisualDescendents())
+ {
+ var c = i as IControl;
+
+ if (c?.IsInitialized == false)
+ {
+ var init = c as ISupportInitialize;
+
+ if (init != null)
+ {
+ init.BeginInit();
+ init.EndInit();
+ }
+ }
+ }
+ }
+
+ if (!IsArrangeValid)
+ {
+ Measure(Size.Infinity);
+ Arrange(new Rect(DesiredSize));
+ }
+ }
+ }
+
///
/// Adds a pseudo-class to be set when a property is true.
///
diff --git a/src/Avalonia.Visuals/Avalonia.Visuals.csproj b/src/Avalonia.Visuals/Avalonia.Visuals.csproj
index 10074c5026..21978720e9 100644
--- a/src/Avalonia.Visuals/Avalonia.Visuals.csproj
+++ b/src/Avalonia.Visuals/Avalonia.Visuals.csproj
@@ -119,6 +119,7 @@
+
diff --git a/src/Avalonia.Visuals/Rendering/IVisualBrushInitialize.cs b/src/Avalonia.Visuals/Rendering/IVisualBrushInitialize.cs
new file mode 100644
index 0000000000..b3209e2462
--- /dev/null
+++ b/src/Avalonia.Visuals/Rendering/IVisualBrushInitialize.cs
@@ -0,0 +1,20 @@
+// 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 System;
+using Avalonia.Media;
+
+namespace Avalonia.Rendering
+{
+ ///
+ /// Internal interface for initializing controls that are to be used as the viusal in a
+ /// .
+ ///
+ public interface IVisualBrushInitialize
+ {
+ ///
+ /// Ensures that the control is ready to use as the visual in a visual brush.
+ ///
+ void EnsureInitialized();
+ }
+}
diff --git a/src/Avalonia.Visuals/Rendering/IVisualBrushRenderer.cs b/src/Avalonia.Visuals/Rendering/IVisualBrushRenderer.cs
index 33d0ee258c..6c410587fe 100644
--- a/src/Avalonia.Visuals/Rendering/IVisualBrushRenderer.cs
+++ b/src/Avalonia.Visuals/Rendering/IVisualBrushRenderer.cs
@@ -1,4 +1,7 @@
-using System;
+// 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 System;
using Avalonia.Media;
namespace Avalonia.Rendering
@@ -8,6 +11,14 @@ namespace Avalonia.Rendering
///
public interface IVisualBrushRenderer
{
+ ///
+ /// Gets the size of the intermediate render target to which the visual brush should be
+ /// drawn.
+ ///
+ /// The visual brush.
+ /// The size of the intermediate render target to create.
+ Size GetRenderTargetSize(VisualBrush brush);
+
///
/// Renders a visual brush to a bitmap.
///
diff --git a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs
index 9edb0251e6..bcd84682be 100644
--- a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs
+++ b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs
@@ -79,6 +79,12 @@ namespace Avalonia.Rendering
{
}
+ Size IVisualBrushRenderer.GetRenderTargetSize(VisualBrush brush)
+ {
+ (brush.Visual as IVisualBrushInitialize)?.EnsureInitialized();
+ return brush.Visual?.Bounds.Size ?? Size.Empty;
+ }
+
void IVisualBrushRenderer.RenderVisualBrush(IDrawingContextImpl context, VisualBrush brush)
{
var visual = brush.Visual;
diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
index 6660dd1ccb..9f3360155b 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
@@ -348,24 +348,27 @@ namespace Avalonia.Direct2D1.Media
{
if (_visualBrushRenderer != null)
{
- TileBrushImplHelper.EnsureInitialized(visualBrush.Visual);
+ var intermediateSize = _visualBrushRenderer.GetRenderTargetSize(visualBrush);
- using (var intermediate = new BitmapRenderTarget(
- _renderTarget,
- CompatibleRenderTargetOptions.None,
- visualBrush.Visual.Bounds.Size.ToSharpDX()))
+ if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1)
{
- using (var ctx = new RenderTarget(intermediate).CreateDrawingContext(_visualBrushRenderer))
+ using (var intermediate = new BitmapRenderTarget(
+ _renderTarget,
+ CompatibleRenderTargetOptions.None,
+ intermediateSize.ToSharpDX()))
{
- intermediate.Clear(null);
- _visualBrushRenderer.RenderVisualBrush(ctx, visualBrush);
+ using (var ctx = new RenderTarget(intermediate).CreateDrawingContext(_visualBrushRenderer))
+ {
+ intermediate.Clear(null);
+ _visualBrushRenderer.RenderVisualBrush(ctx, visualBrush);
+ }
+
+ return new ImageBrushImpl(
+ visualBrush,
+ _renderTarget,
+ new D2DBitmapImpl(intermediate.Bitmap),
+ destinationSize);
}
-
- return new ImageBrushImpl(
- visualBrush,
- _renderTarget,
- new D2DBitmapImpl(intermediate.Bitmap),
- destinationSize);
}
}
else
@@ -373,10 +376,8 @@ namespace Avalonia.Direct2D1.Media
throw new NotSupportedException("No IVisualBrushRenderer was supplied to DrawingContextImpl.");
}
}
- else
- {
- return new SolidColorBrushImpl((Avalonia.Media.SolidColorBrush)null, _renderTarget);
- }
+
+ return new SolidColorBrushImpl(null, _renderTarget);
}
public void PushGeometryClip(Avalonia.Media.Geometry clip)