[UWP] Use BorderEffect of Win2D to tile pictures

1. WPF has but UWP does not have picture tiling

In WPF, images can be tiled simply by setting the TileMode property of ImageSource to Tile. These documents in WPF can be seen in detail:

ImageBrush class (System.Windows.Media) Microsoft Docs

TileBrush class (System.Windows.Media) Microsoft Docs

TileBrush.TileMode l Properties (System.Windows.Media) Microsoft Docs

I have hardly used the WPF picture tiling function, but remember its use as a basic knowledge.I thought there was definitely such a basic function in UWP that I had no doubt about it, so I was really shocked when I found out in UWP that such a basic thing was not there.

The image above shows the WPF version of TileBrush on the left and the UWP version on the right, where you can see that the UWP version has less than half the functionality.

For such a small class, I don't think it's necessary to simplify it here.Fortunately picture tiles can be used in Win2D BorderEffect Realization.

2. Image tiling in UWP

<Grid>
    <Rectangle x:Name="Background" />
</Grid>

Assuming you have more than one XAML, to apply a composite brush on an element named Background, first reference Win2D.uwp nuget package, then refer to the official documentation Composite Brush The section uses pictures to create a composite brush:

var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
var imageBrush = compositor.CreateSurfaceBrush();
var loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///110Strawberry.png"));
imageBrush.Surface = loadedSurface;
imageBrush.Stretch = CompositionStretch.None;

Just create a SpriteVisual and apply it to the VisualTree of Background, which, by the way, is this picture:

However, a BorderEffect is also required to achieve tiling:

var borderEffect = new BorderEffect
{
    Source = new CompositionEffectSourceParameter("source")
};

var effectFactory = compositor.CreateEffectFactory(borderEffect);
var effectBrush = effectFactory.CreateBrush();
effectBrush.SetSourceParameter("source", imageBrush);

var sprite = compositor.CreateSpriteVisual();
sprite.Brush = effectBrush;

var backgroundVisual = ElementCompositionPreview.GetElementVisual(Background);
var bindSizeAnimation = compositor.CreateExpressionAnimation("backgroundVisual.Size");
bindSizeAnimation.SetReferenceParameter("backgroundVisual", backgroundVisual);
sprite.StartAnimation("Size", bindSizeAnimation);

ElementCompositionPreview.SetElementChildVisual(Background, sprite);

In summary, BorderEffect uses imageBrush as its Source, while others retain the default value. Applying it to the VisualTree of Background works as follows:

This is not the tiling I want.This is because at this point ExtendX and ExtendY keep the default Clamp value, which causes BorderEffect to duplicate the properties of the image edge.These two properties need to be set to Wrap if I want to achieve the tile I want:

borderEffect.ExtendX = CanvasEdgeBehavior.Wrap;
borderEffect.ExtendY = CanvasEdgeBehavior.Wrap;

It's not tiled from the top left, it's different from what I thought, but that's all.By the way, ExtendX and ExtendY can also be set to Mirror as follows:

3. Bind Size

var backgroundVisual = ElementCompositionPreview.GetElementVisual(Background);
var bindSizeAnimation = compositor.CreateExpressionAnimation("backgroundVisual.Size");
bindSizeAnimation.SetReferenceParameter("backgroundVisual", backgroundVisual);
sprite.StartAnimation("Size", bindSizeAnimation);

Finally, by the way, there's a code like this that's not covered in the above code, which is used to dynamically size SpriteVisual.ExpressionAnimation has two features: running and never stopping. Creating ExpressionAnimation and running animations on SpriteVisual actually binds SpriteVisual's Size to the value of backgroundVisual's Size forever.Simply subscribing to SizeChanged events can do the same thing, with less code.

4. Conclusion

How could such a simple function require so much code or a simpler implementation?But everything has to be viewed dialectically. Fortunately, it is so complex that I have a blog.

Stack Overflow Other proposals are given for reference.

5. Reference

Border effect - Win32 apps _ Microsoft Docs

Composite Brush - Windows UWP applications Microsoft Docs

Win2D Quick Start for Win2D - h82258652 - Blog Park

Relationship-based animation - Windows UWP applications Microsoft Docs

c# - UWP - How to tile a background image - Stack Overflow

Tags: ASP.NET Windows less

Posted on Mon, 06 Jan 2020 03:53:56 -0800 by shadypalm88