.NET MAUI, Microsoft’s new cross-platform UI framework to build apps in a single project is soon coming. .NET MAUI is the evolution of Xamarin Forms thus, it has every UI View Xamarin Forms offered and in addition to that, a few new UI views. We are going to discuss how to use some of these new .NET MAUI Views in this post. If you want to know more about .NET MAUI, and have a deep introduction to this new framework, check out this post.
Not until recently Xamarin Forms had only the Frame to provide these features (The frame wasn’t flexible enough). The Xamarin community toolkit brought us the CornerRadiusEffect, and ShadowEffect. These enabled us to add shadows and round corners to our views. Prior to that, there were third-party plugins that were built by the community to provide the functionalities these new .NET MAUI Views now provide. Some of these third-party views include The PancakeView and the BorderView… The GraphicsView on the other hand is a brand new control that we can think of as a canvas where we can create and draw whatever we want. I’m glad that these new .NET MAUI Views were added to the framework. In this post, we’ll play with them.
HERE is the source code for this article.
Shadows
Views in .NET MAUI have a shadow property. By setting a new instance of a shadow in this property, you can add a shadow to any view. This property is derived from VisualElement. Meaning every view that derives from VisualElement, can have a shadow. For example, below I add a shadow to a label in XAML.
1 2 3 | <Label.Shadow> <Shadow/> </Label.Shadow> |
Now, we want a better shadow. We want it to have a given color or even a gradient, we want it to have a given opacity. We also want to position this shadow at a specific position from the given view. All these are possible, the shadow class has several properties available for you to use. To know all the properties available, check the source code (Docs are not yet very detailed at this time).
Below we created our shadow and added sliders to control the value of some of its properties to configure them live.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <Label.Shadow> <Shadow Offset="0,0" Opacity="{Binding Source={x:Reference ShadowOpacitySlider}, Path=Value}" Radius="{Binding Source={x:Reference ShadowRadiusSlider}, Path=Value }"> <Shadow.Brush> <LinearGradientBrush> <GradientStop Color="Gold" Offset="0.1" /> <GradientStop Color="LimeGreen" Offset="1.0" /> </LinearGradientBrush> </Shadow.Brush> </Shadow> </Label.Shadow> |
We also modify the shadow offset when a slider’s value changes. This is done in the code behind XAML.
1 2 3 4 5 6 | private void ShadowSlider_ValueChanged(object sender, ValueChangedEventArgs e) { AwesomeLabel.Shadow.Offset = new Point(30 - e.NewValue, e.NewValue); } |
Here is the result, showing how a change in these properties affects the shadow.
Borders and Corners
MAUI’s border view has everything we need. It has several properties that go beyond giving round corners, or simple borders. I really love this view and I like the fact that the MAUI team has made it really flexible.
We can give the shape we want to our border. This is done with its StrokeShape property. In the example below, we give it the shape of a rounded rectangle.
1 2 3 4 | <Border.StrokeShape> <RoundRectangle CornerRadius="80,0,80,0" /> </Border.StrokeShape> |
We can also chose to give a simple color to our border’s stroke, or give it a gradient. As shown below.
1 2 3 4 5 6 7 8 9 | <Border.Stroke> <LinearGradientBrush EndPoint="0,1"> <GradientStop Color="Gold" Offset="0.1" /> <GradientStop Color="LimeGreen" Offset="1.0" /> </LinearGradientBrush> </Border.Stroke> |
We can also adjust the border’s thickness with the “StrokeThickness” property.
But the most interesting properties are those that folow. As mentioned in the docs.
StrokeDashArray
, of typeDoubleCollection
, which represents a collection ofdouble
values that indicate the pattern of dashes and gaps that make up the border.
StrokeDashOffset
, of typedouble
, specifies the distance within the dash pattern where a dash begins. The default value of this property is 0.0.
StrokeLineCap
, of typePenLineCap
, describes the shape at the start and end of its line. The default value of this property isPenLineCap.Flat
.
StrokeLineJoin
, of typePenLineJoin
, specifies the type of join that is used at the vertices of the stroke shape. The default value of this property isPenLineJoin.Miter
.
StrokeMiterLimit
, of typedouble
, specifies the limit on the ratio of the miter length to half the stroke thickness. The default value of this property is 10.0.
We will play with the values of these properties to know exactly what happens when we change their values in a specific way. For this, I created a demo app you can find on github.
In the xaml, we bind the border’s stroke thickness to a slider’s value.
1 2 | <Border x:Name="MainBorder" StrokeThickness="{Binding Value, Source={x:Reference ThicknessSlider}}" |
Then in the code behind, we set a few more properties when their values change at runtime.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | private void LineJoinPicker_SelectedIndexChanged(object sender, EventArgs e) { PenLineJoin borderLineJoin = StrokeDashPicker.SelectedIndex switch { 0 => PenLineJoin.Miter, 1 => PenLineJoin.Round, 2 => PenLineJoin.Bevel, _ => PenLineJoin.Miter }; MainBorder.StrokeLineJoin = borderLineJoin; } private void LineCapPicker_SelectedIndexChanged(object sender, EventArgs e) { PenLineCap borderLineCap = LineCapPicker.SelectedIndex switch { 0 => PenLineCap.Flat, 1 => PenLineCap.Round, 2 => PenLineCap.Square, _ => PenLineCap.Flat }; MainBorder.StrokeLineCap = borderLineCap; } private void StrokeDashPicker_SelectedIndexChanged(object sender, EventArgs e) { var doubleCollectionConverter = new DoubleCollectionConverter(); var doubleCollection = (DoubleCollection)doubleCollectionConverter.ConvertFromString(StrokeDashPicker.SelectedItem.ToString()); MainBorder.StrokeDashArray = doubleCollection; } |
You can see the results in the GIF below.
.NET MAUI GraphicsView
Another new .NET MAUI View is the GraphicsView. This is a very interesting view. It acts like a canvas where you can draw what ever you want. You can even draw strings, picutres, or export what is drawn on it as a PDF. It really is flexible.
The graphics view takes an “IDrawable” object. This object contains the code to draw on a canvas. The method in which items are drawn is:
1 2 | public void Draw(ICanvas canvas, RectangleF rect) |
Where “rect” is a structure with the dimensions of the graphics view on which you are drawing and “canvas” the canvas on which you draw your shapes.
The ICanvas object passed as parameter contains several methods to draw different shapes on the canvas. You can change the color of the shape you’re about to draw at any time. This is done by setting the “StrokeColor” property of canvas.
Below, we will draw a few shapes. First, we will use the methods provided by the framework. Then we will draw a shape with our own method that is, using paths.
1 2 3 | canvas.DrawRectangle(50, 100, 100, 50); canvas.DrawEllipse(100, 200, 100, 50); |
We draw a triangle, using a path.
1 2 3 4 5 6 7 8 | canvas.StrokeColor = Colors.Orange; var path = new PathF(); path.MoveTo(250, 100); path.LineTo(200, 150); path.LineTo(300, 150); path.Close(); canvas.DrawPath(path); |
I won’t talk much about this view because its documentation is very detailed. I even think it is the .NET MAUI view with the most documentation at the time of writing this. I might dive deeper in this view’s features later, in a subsequent post.
Conclusion
.NET MAUI comes with a lot of exciting features and ameliorations. The above views were needed in Xamarin Forms, so much so that third-party packages were created like the PancakeView and the Xamarin Community Toolkit’s Shadow Effect, to fill the gap. Now we have them in MAUI. One of the awesome features brought to you by .NET MAUI is handlers. To understand what handlers are, check out this deep introduction to the topic.
References
https://docs.microsoft.com/fr-fr/dotnet/maui/user-interface/controls/border?WT.mc_id=DT-MVP-5003277
Follow me on social media and stay updated