Extensions for 3rd Party Controls

Version: v9.x

mgLib.MauiMarkup library can also generate extension methods for controls from third-party libraries. To achieve this, you should utilize the MauiMarkupAttribute provided by FmgLib.MauiMarkup.

Simply specify the control for which you want to create extension methods as [MauiMarkup(typeof(YourControl))].

The constructor method of the MauiMarkup() attribute automatically generates extension methods for BindableProperties and Events found within the type provided as an argument. You can provide a minimum of 1 type inside the constructor method, and there is no maximum limit. Multiple MauiMarkup attributes can be added to a single class.

NOTE: Suppose that if a property inherited from base classes has been redefined with the new keyword in the class where you want to create a Fluent Method, the name of the new Fluent Method will be PropertyName + New.

For example, since the Background property in the SfAvatarView class is redefined with new and is the same as the Background in VisualElement, to prevent errors, the Fluent Method name for the Background property of the SfAvatarView class will be BackgroundNew.

Let's look at an example:

using FmgLib.MauiMarkup;

namespace GeneratedExam;

[MauiMarkup(typeof(ZXing.Net.Maui.Controls.BarcodeGeneratorView))]
public class MyBarcodeGeneratorView { }

[MauiMarkup(typeof(ZXing.Net.Maui.Controls.CameraView))]
public class MyCameraView { }


[MauiMarkup(typeof(ZXing.Net.Maui.Controls.CameraBarcodeReaderView))]
public class MyCameraBarcodeReaderView { }

[MauiMarkup(typeof(SkiaSharp.Extended.UI.Controls.SKLottieView))]
public class MySkLottieView { }

Or instead of dealing with it like this, it can be used like this:

using Microsoft.Extensions.Logging;
using FmgLib.MauiMarkup;
using SkiaSharp.Extended.UI.Controls;
using ZXing.Net.Maui.Controls;
using UraniumUI.Material.Controls;
namespace MauiApp1
{
    [MauiMarkup(typeof(CameraView))]
    [MauiMarkup(typeof(SKLottieView), typeof(SKFileLottieImageSource), typeof(DataGrid))]
    [MauiMarkup(typeof(SKConfettiView), typeof(BarcodeGeneratorView),typeof(InputField),typeof(EditorField),typeof(TextField))]
    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });

#if DEBUG
    		builder.Logging.AddDebug();
#endif
            return builder.Build();
        }
    }
}

CameraView class from ZXing.Net.Maui.Controls library:

using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using System;

namespace ZXing.Net.Maui.Controls
{
	public partial class CameraView : View, ICameraView
	{
		public event EventHandler<CameraFrameBufferEventArgs> FrameReady;

		void ICameraFrameAnalyzer.FrameReady(CameraFrameBufferEventArgs e)
			=> FrameReady?.Invoke(this, e);

		public static readonly BindableProperty IsTorchOnProperty =
			BindableProperty.Create(nameof(IsTorchOn), typeof(bool), typeof(CameraView), defaultValue: true);

		public bool IsTorchOn
		{
			get => (bool)GetValue(IsTorchOnProperty);
			set => SetValue(IsTorchOnProperty, value);
		}

		public static readonly BindableProperty CameraLocationProperty =
			BindableProperty.Create(nameof(CameraLocation), typeof(CameraLocation), typeof(CameraView), defaultValue: CameraLocation.Rear);

		public CameraLocation CameraLocation
		{
			get => (CameraLocation)GetValue(CameraLocationProperty);
			set => SetValue(CameraLocationProperty, value);
		}

		public void AutoFocus()
			=> StrongHandler?.Invoke(nameof(AutoFocus), null);

		public void Focus(Point point)
			=> StrongHandler?.Invoke(nameof(Focus), point);

		CameraViewHandler StrongHandler 
			=> Handler as CameraViewHandler;
	}
}

The CameraViewExtension class created using the MauiMarkup attribute will be as follows:

//
// <auto-generated-fmglib-mauimarkup-generator />
//


namespace FmgLib.MauiMarkup;

public static partial class CameraViewExtension
{
        public static T CameraLocation<T>(this T self,
            ZXing.Net.Maui.CameraLocation cameraLocation)
            where T : ZXing.Net.Maui.Controls.CameraView
        {
            self.SetValue(ZXing.Net.Maui.Controls.CameraView.CameraLocationProperty, cameraLocation);
            return self;
        }
        
        public static T CameraLocation<T>(this T self, Func<PropertyContext<ZXing.Net.Maui.CameraLocation>, IPropertyBuilder<ZXing.Net.Maui.CameraLocation>> configure)
            where T : ZXing.Net.Maui.Controls.CameraView
        {
            var context = new PropertyContext<ZXing.Net.Maui.CameraLocation>(self, ZXing.Net.Maui.Controls.CameraView.CameraLocationProperty);
            configure(context).Build();
            return self;
        }
        
        public static SettersContext<T> CameraLocation<T>(this SettersContext<T> self,
            ZXing.Net.Maui.CameraLocation cameraLocation)
            where T : ZXing.Net.Maui.Controls.CameraView
        {
            self.XamlSetters.Add(new Setter { Property = ZXing.Net.Maui.Controls.CameraView.CameraLocationProperty, Value = cameraLocation });
            return self;
        }
        
        public static SettersContext<T> CameraLocation<T>(this SettersContext<T> self, Func<PropertySettersContext<ZXing.Net.Maui.CameraLocation>, IPropertySettersBuilder<ZXing.Net.Maui.CameraLocation>> configure)
            where T : ZXing.Net.Maui.Controls.CameraView
        {
            var context = new PropertySettersContext<ZXing.Net.Maui.CameraLocation>(self.XamlSetters, ZXing.Net.Maui.Controls.CameraView.CameraLocationProperty);
            configure(context).Build();
            return self;
        }
        
        public static T IsTorchOn<T>(this T self,
            bool isTorchOn)
            where T : ZXing.Net.Maui.Controls.CameraView
        {
            self.SetValue(ZXing.Net.Maui.Controls.CameraView.IsTorchOnProperty, isTorchOn);
            return self;
        }
        
        public static T IsTorchOn<T>(this T self, Func<PropertyContext<bool>, IPropertyBuilder<bool>> configure)
            where T : ZXing.Net.Maui.Controls.CameraView
        {
            var context = new PropertyContext<bool>(self, ZXing.Net.Maui.Controls.CameraView.IsTorchOnProperty);
            configure(context).Build();
            return self;
        }
        
        public static SettersContext<T> IsTorchOn<T>(this SettersContext<T> self,
            bool isTorchOn)
            where T : ZXing.Net.Maui.Controls.CameraView
        {
            self.XamlSetters.Add(new Setter { Property = ZXing.Net.Maui.Controls.CameraView.IsTorchOnProperty, Value = isTorchOn });
            return self;
        }
        
        public static SettersContext<T> IsTorchOn<T>(this SettersContext<T> self, Func<PropertySettersContext<bool>, IPropertySettersBuilder<bool>> configure)
            where T : ZXing.Net.Maui.Controls.CameraView
        {
            var context = new PropertySettersContext<bool>(self.XamlSetters, ZXing.Net.Maui.Controls.CameraView.IsTorchOnProperty);
            configure(context).Build();
            return self;
        }
        
        public static T OnFrameReady<T>(this T self, System.EventHandler<ZXing.Net.Maui.CameraFrameBufferEventArgs> handler)
            where T : ZXing.Net.Maui.Controls.CameraView
        {
            self.FrameReady += handler;
            return self;
        }
        
        public static T OnFrameReady<T>(this T self, System.Action<T> action)
            where T : ZXing.Net.Maui.Controls.CameraView
        {
            self.FrameReady += (o, arg) => action(self);
            return self;
        }
        
}

For example, let's write the sample code for the TextField and SKLottieView Controls:

new TextField()
.Title("Password")
.TitleColor(Colors.LightGray)
.AccentColor(Colors.CadetBlue)
.TextColor(Colors.White)
.IsPassword(true),

new SKLottieView()
.Source(new SKFileLottieImageSource().File("iconapp.json"))
.RepeatCount(-1)
.HeightRequest(250)
.WidthRequest(250)

With the MauiMarkupAttachedPropAttribute, you can easily create extension methods for AttachedProperties within Control classes from third-party libraries. The constructor's first parameter takes the type of the Control class, the second parameter takes the name of the AttachedProperty, the third parameter takes the value type that the AttachedProperty can accept, and the fourth parameter takes the type to which the AttachedProperty will be applied.

Example usage:

[MauiMarkupAttachedProp(typeof(InputKit.Shared.Controls.FormView), nameof(InputKit.Shared.Controls.FormView.IsSubmitButtonProperty), typeof(bool), typeof(Button))]
[MauiMarkup(typeof(InputKit.Shared.Controls.FormView))]
public class MyFormView { }

OR


using Microsoft.Extensions.Logging;
using FmgLib.MauiMarkup;

namespace MauiApp1
{
    [MauiMarkupAttachedProp(typeof(InputKit.Shared.Controls.FormView), nameof(InputKit.Shared.Controls.FormView.IsSubmitButtonProperty), typeof(bool), typeof(Button))]
    [MauiMarkup(typeof(InputKit.Shared.Controls.FormView))]
    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });

#if DEBUG
    		builder.Logging.AddDebug();
#endif
            return builder.Build();
        }
    }
}

The usage of the AttachedProperty in the Button class will be as follows:

new Button()
.Text("Login")
.FontAttributes(Bold)
.FormViewIsSubmitButton(true)