BindableProps 1.1.1-beta

.NET 6.0
This is a prerelease version of BindableProps.
There is a newer version of this package available.
See the version list below for details.
dotnet add package BindableProps --version 1.1.1-beta
NuGet\Install-Package BindableProps -Version 1.1.1-beta
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BindableProps" Version="1.1.1-beta" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add BindableProps --version 1.1.1-beta
#r "nuget: BindableProps, 1.1.1-beta"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install BindableProps as a Cake Addin
#addin nuget:?package=BindableProps&version=1.1.1-beta&prerelease

// Install BindableProps as a Cake Tool
#tool nuget:?package=BindableProps&version=1.1.1-beta&prerelease

BindableProps

NuGet Build Status

I spend hours to save your moments.

This library helps you to reduce writing boilerplate code when creating your custom UI components.

Example Usage

Let say you want to create your own text input. Here's how it looks:

namespace MyMauiApp.Controls;

public class TextInput : ContentView
{
    public string Text
    {
        get => (string)GetValue(TextInput.TextProperty);
        set => SetValue(TextInput.TextProperty, value);
    }

    public static readonly BindableProperty TextProperty = BindableProperty.Create(
        nameof(Text), typeof(string), typeof(TextInput), string.Empty
        );

    public string PlaceHolder
    {
        get => (string)GetValue(TextInput.PlaceHolderProperty);
        set => SetValue(TextInput.PlaceHolderProperty, value);
    }

    public static readonly BindableProperty PlaceHolderProperty = BindableProperty.Create(
        nameof(PlaceHolder), typeof(string), typeof(TextInput), string.Empty
        );


    public TextInput()
    {
        // Implement your logic
    }
}

With BindableProps, your code will become like this:

using BindableProps;

namespace MyMauiApp.Controls;

// Notice: Your class must be partial class
public partial class TextInput : ContentView
{
    [BindableProp]
    string text;

    [BindableProp]
    string placeHolder;


    public TextInput()
    {
        // This piece is same as above
    }
}

The real magic happens at Solution Explorer > Dependencies > Analyzers > BindablePropsSG

image-20220704231041505

What you would see in TextInput.g.cs is the boilerplate code which you had to write. I'll write them for you!

using BindableProps;

namespace MyMauiApp.Controls
{
    public partial class TextInput
    {

        public static readonly BindableProperty TextProperty = BindableProperty.Create(
            nameof(Text),
            typeof(string),
            typeof(TextInput),
            default,
            BindingMode.Default,
            null,
            null,
            null,
            null,
            null
        );

        public string Text
        {
            get => text;
            set 
            { 
                text = value;
                SetValue(TextInput.TextProperty, text);
            }
        }

        public static readonly BindableProperty PlaceHolderProperty = BindableProperty.Create(
            nameof(PlaceHolder),
            typeof(string),
            typeof(TextInput),
            default,
            BindingMode.Default,
            null,
            null,
            null,
            null,
            null
        );

        public string PlaceHolder
        {
            get => placeHolder;
            set 
            { 
                placeHolder = value;
                SetValue(TextInput.PlaceHolderProperty, placeHolder);
            }
        }

    }
}

The above example is the minimal amount of code to work. Here is the complete features:

public partial class TextInput : ContentView
{
    // Create prop with a few settings
    [BindableProp(DefaultBindingMode = ((int)BindingMode.TwoWay))]
    string text = "From every time";

    // Full setting
    [BindableProp(
        DefaultBindingMode = ((int)BindingMode.OneWay),
        ValidateValueDelegate = nameof(ValidateValue),
        PropertyChangedDelegate = nameof(PropertyChangedDelegate),
        PropertyChangingDelegate = nameof(PropertyChangingDelegate),
        CoerceValueDelegate = nameof(CoerceValueDelegate),
        CreateDefaultValueDelegate = nameof(CreateDefaultValueDelegate)
        )]
    string placeHolder = "Always!";

    static bool ValidateValue(BindableObject bindable, object value)
    {
        return true;
    }

    static void PropertyChangedDelegate(BindableObject bindable, object oldValue, object newValue)
    {
        // Do something
    }

    static void PropertyChangingDelegate(BindableObject bindable, object oldValue, object newValue)
    {
        // Do something
    }

    static object CoerceValueDelegate(BindableObject bindable, object value)
    {
        // Do something
        return 0;
    }

    static object CreateDefaultValueDelegate(BindableObject bindable)
    {
        // Do something
        return string.Empty;
    }
}

And the corresponding result would like:

public partial class TextInput
    {
        public static readonly BindableProperty TextProperty = BindableProperty.Create(
            nameof(Text),
            typeof(string),
            typeof(TextInput),
            "From every time",
            ((int)BindingMode.TwoWay),
            null,
            null,
            null,
            null,
            null
        );

        public string Text
        {
            get => text;
            set 
            { 
                text = value;
                SetValue(TextInput.TextProperty, text);
            }
        }

        public static readonly BindableProperty PlaceHolderProperty = BindableProperty.Create(
            nameof(PlaceHolder),
            typeof(string),
            typeof(TextInput),
            "Always!",
            ((int)BindingMode.OneWay),
            ValidateValue,
            PropertyChangedDelegate,
            PropertyChangingDelegate,
            CoerceValueDelegate,
            CreateDefaultValueDelegate
        );

        public string PlaceHolder
        {
            get => placeHolder;
            set 
            { 
                placeHolder = value;
                SetValue(TextInput.PlaceHolderProperty, placeHolder);
            }
        }

    }

Finally, you can use your component in other page/view like a normal component. For example, at MainPage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:MyMauiApp.ViewModels"
             xmlns:controls="clr-namespace:MyMauiApp.Controls"
             x:Class="MyMauiApp.MainPage"
             x:DataType="vm:MainPageViewModel">
    
    <controls:TextInput PlaceHolder="Say you do"
                        Text="{Binding MyLoveStory, Mode=TwoWay}" />
</ContentPage>

Roadmap

The BindableProp along is just not enough for covering all use-cases of BindableProperty. Planning features:

Attribute Equivalent/Description
BindableAttachedProp BindableProperty.CreateAttached
BindableAttachedReadOnlyProp BindablePropertyKey.CreateAttachedReadOnly
BindableReadOnlyProp BindablePropertyKey.CreateReadOnly
AllBindableProps Put this to your class,<br />Default BindableProp to all field members
IgnoredProp AllBindableProps should ignore this field
Product Versions
.NET net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows net7.0 net7.0-android net7.0-ios net7.0-maccatalyst net7.0-macos net7.0-tvos net7.0-windows
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.3.4 91 1/8/2023
1.3.3 82 1/8/2023
1.3.2 80 1/7/2023
1.3.1 78 1/7/2023
1.3.0 82 1/6/2023
1.2.1 79 1/5/2023
1.2.0 256 7/10/2022
1.2.0-beta 66 7/10/2022
1.1.9 233 7/10/2022
1.1.8 230 7/10/2022
1.1.8-beta 85 7/9/2022
1.1.7-beta 65 7/8/2022
1.1.3-beta 56 7/8/2022
1.1.2-beta 59 7/8/2022
1.1.1-beta 65 7/8/2022
1.1.0-beta 64 7/7/2022
1.0.7-beta 81 7/5/2022
1.0.6-beta 63 7/4/2022
1.0.4-beta 78 7/3/2022
1.0.3-beta 78 7/3/2022
1.0.2-beta 82 7/3/2022
1.0.1-beta 74 7/1/2022
1.0.0-beta 67 7/1/2022