Skip to content

Commit

Permalink
Added validateValue functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
rrmanzano committed Aug 30, 2022
1 parent da23534 commit 83ebc57
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 34 deletions.
158 changes: 131 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ PM> Install-Package M.BindableProperty.Generator
````

## Usage - Simple implementation
Just decorate field with the Bindable attribute.
Just decorate the field with the Bindable attribute.

```csharp
using Maui.BindableProperty.Generator.Core;

public partial class CustomEntry : ContentView
{
[AutoBindable]
private string _placeholder;
private readonly string _placeholder;
}
```
the prevoius code will generate this:
Expand All @@ -42,16 +42,27 @@ the prevoius code will generate this:
}
```

## Usage - Custom property name
Just decorate field with the Bindable attribute.
## Options

| Option | Description | Type |
| ------------- | ------------------------------ | ------------------------------ |
| `PropertyName` | Specifies the prefix used to create the BindableProperty, if `PropertyName` is null, then will take the name of the field removing the underscores and using PascalCase. Example: `_tex_t` will be transformed to `Text`. | `string` |
| `OnChanged` | Specifies the name of the method to be executed when the property changed. | `string` |
| `DefaultValue` | Specifies the "text/value" that will be used as default. Example: `default(string)`| `string` |
| `DefaultBindingMode` | Specifies the "BindingMode" as string that will be used as default. Options: `Default/TwoWay/OneWay/OneWayToSource/OneTime`. Example: `nameof(BindingMode.TwoWay)`| `string` |
| `HidesUnderlyingProperty` | Specifies if the BindingProperty will hide the current implementation. | `bool` |
| `ValidateValue` | Specifies the name of the method to be executed to validate the values. | `string` |

## Usage - **PropertyName**
Just decorate the field with the Bindable attribute.

```csharp
using Maui.BindableProperty.Generator.Core;

public partial class CustomEntry : ContentView
{
[AutoBindable(PropertyName = "Text")]
private string _t;
private readonly string _t;
}
```
the prevoius code will generate this:
Expand All @@ -73,18 +84,18 @@ the prevoius code will generate this:
}
```

## Usage - OnChanged method
## Usage - **OnChanged**

### Example 1 - No Parameters
Just decorate field with the Bindable attribute.
Just decorate the field with the Bindable attribute.

```csharp
using Maui.BindableProperty.Generator.Core;

public partial class HeaderControl : ContentView
{
[AutoBindable(OnChanged = nameof(UpdateDisplayName))]
private string _firstName;
private readonly string _firstName;

private void UpdateDisplayName()
{
Expand Down Expand Up @@ -119,15 +130,15 @@ the prevoius code will generate this:
```

### Example 2 - One Parameter
Just decorate field with the Bindable attribute. The 'UpdateDisplayName' method must have only one parameter (must match the type of the field)
Just decorate the field with the Bindable attribute. The 'UpdateDisplayName' method must have only one parameter (must match the type of the field)

```csharp
using Maui.BindableProperty.Generator.Core;

public partial class HeaderControl : ContentView
{
[AutoBindable(OnChanged = nameof(UpdateDisplayName))]
private string _firstName;
private readonly string _firstName;

private void UpdateDisplayName(string newValue)
{
Expand Down Expand Up @@ -162,15 +173,15 @@ the prevoius code will generate this:
```

### Example 3 - Two Parameters
Just decorate field with the Bindable attribute. The 'UpdateDisplayName' method must have two parameters (must match the type of the field)
Just decorate the field with the Bindable attribute. The 'UpdateDisplayName' method must have two parameters (must match the type of the field)

```csharp
using Maui.BindableProperty.Generator.Core;

public partial class HeaderControl : ContentView
{
[AutoBindable(OnChanged = nameof(UpdateDisplayName))]
private string _firstName;
private readonly string _firstName;

private void UpdateDisplayName(string oldValue, string newValue)
{
Expand Down Expand Up @@ -204,18 +215,18 @@ the prevoius code will generate this:
}
```

## Usage - Set default value
## Usage - **DefaultValue**

### Example 1 - DateTime
Just decorate field with the Bindable attribute and add the "text/value" that you want to use as default value.
Just decorate the field with the Bindable attribute and add the "text/value" that you want to use as default value.

```csharp
using Maui.BindableProperty.Generator.Core;

public partial class HeaderControl : ContentView
{
[AutoBindable(DefaultValue = "DateTime.Now")]
private DateTime _birthDate;
private readonly DateTime _birthDate;
}
```
the prevoius code will generate this:
Expand All @@ -238,15 +249,15 @@ the prevoius code will generate this:
```

### Example 2 - String
Just decorate field with the Bindable attribute and add the "text/value" that you want to use as default value.
Just decorate the field with the Bindable attribute and add the "text/value" that you want to use as default value.

```csharp
using Maui.BindableProperty.Generator.Core;

public partial class HeaderControl : ContentView
{
[AutoBindable(DefaultValue = "USA")]
private string _country;
private readonly string _country;
}
```
the prevoius code will generate this:
Expand All @@ -268,16 +279,16 @@ the prevoius code will generate this:
}
```

## Usage - Set default BindingMode
Just decorate field with the Bindable attribute and add the "BindingMode" that you want to use as default value.
## Usage - **DefaultBindingMode**
Just decorate the field with the Bindable attribute and add the "BindingMode" that you want to use as default value.

```csharp
using Maui.BindableProperty.Generator.Core;

public partial class HeaderControl : ContentView
{
[AutoBindable(DefaultBindingMode = nameof(BindingMode.TwoWay))]
private string _firstName;
private readonly string _firstName;
}
```
the prevoius code will generate this:
Expand All @@ -300,8 +311,8 @@ the prevoius code will generate this:
}
```

## Usage - Hide existing BindableProperties
Just decorate field with the Bindable attribute and set "HidesUnderlyingProperty = true".
## Usage - **HidesUnderlyingProperty**
Just decorate the field with the Bindable attribute and set "HidesUnderlyingProperty = true".

```csharp
using Maui.BindableProperty.Generator.Core;
Expand Down Expand Up @@ -330,13 +341,106 @@ the prevoius code will generate this:
}
```

## Usage - **ValidateValue**
### Example 1 - Non-Static Method
Just decorate the field with the Bindable attribute. The 'ValidateNotNull' method must have two parameters (one of type BindableObject and the second one must be the same as the field)

```csharp
using Maui.BindableProperty.Generator.Core;

public partial class HeaderControl : ContentView
{
[AutoBindable(ValidateValue = nameof(ValidateIsNullOrEmpty))]
private readonly string? _country;

private bool ValidateIsNullOrEmpty(BindableObject _, string? value)
{
// Do stuff here
return !string.IsNullOrEmpty(value);
}
}
```
the prevoius code will generate this:
```csharp
public partial class HeaderControl
{
public static readonly Microsoft.Maui.Controls.BindableProperty CountryProperty =
Microsoft.Maui.Controls.BindableProperty.Create(
nameof(Country),
typeof(string),
typeof(HeaderControl),
validateValue: __ValidateIsNullOrEmpty);

public string? Country
{
get => (string?)GetValue(CountryProperty);
set => SetValue(CountryProperty, value);
}

private static bool __ValidateIsNullOrEmpty(Microsoft.Maui.Controls.BindableObject bindable, object value)
{
var ctrl = (HeaderControl)bindable;
return ctrl.ValidateIsNullOrEmpty(ctrl, (string?)value);
}
}
```
### Example 2 - Static Method
Just decorate the field with the Bindable attribute. The 'ValidateNotNull' method must have two parameters (one of type BindableObject and the second one must be object type)

```csharp
using Maui.BindableProperty.Generator.Core;

public partial class HeaderControl : ContentView
{
[AutoBindable(ValidateValue = nameof(ValidateNotNull))]
private readonly string? _country;

private static bool ValidateNotNull(BindableObject _, object value) => value != null;
}
```
the prevoius code will generate this:
```csharp
public partial class HeaderControl
{
public static readonly Microsoft.Maui.Controls.BindableProperty CountryProperty =
Microsoft.Maui.Controls.BindableProperty.Create(
nameof(Country),
typeof(string),
typeof(HeaderControl),
defaultValue: default(string?),
validateValue: ValidateNotNull);

public string? Country
{
get => (string?)GetValue(CountryProperty);
set => SetValue(CountryProperty, value);
}
}
```

## Do you want to remove the compiler warning CS0169 ?
```csharp
using Maui.BindableProperty.Generator.Core;

public partial class HeaderControl : ContentView
{
#pragma warning disable CS0169

[AutoBindable]
private readonly string? _country;

#pragma warning restore CS0169
}
```

## Project status

- ✅ Simple implementation - Done
- ✅ Custom property name - Done
- ✅ Custom Parameters - Done
- ✅ OnChanged method - Done
- ✅ OnChanged method overloading - Done
-`PropertyName` - Done
-`OnChanged` - Done
-`DefaultValue` - Done
-`DefaultBindingMode` - Done
-`HidesUnderlyingProperty` - Done
-`ValidateValue` - Done

## Extra info
This repo is using part of the code of [CodeWriter](https://github.com/SaladLab/CodeWriter "CodeWriter") to generate the CSharp files, thanks to the author.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
<Entry
Text="{Binding Source={x:Reference this},Path=Country}" />

<Label Text="ZipCode"/>
<Entry
Text="{Binding Source={x:Reference this},Path=ZipCode}" />

<Label
Text="Full Name : " />
<Label
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ namespace Maui.BindableProperty.Generator.Demo.CustomControls
{
public partial class HeaderControl : VerticalStackLayout
{
private static bool ValidateNotNull(BindableObject _, object value) => value != null;

private bool ValidateIsNullOrEmpty(BindableObject _, string? value)
{
// Do stuff here
return !string.IsNullOrEmpty(value);
}

#pragma warning disable CS0169

[AutoBindable(OnChanged = nameof(UpdateDisplayName))]
Expand All @@ -15,9 +23,12 @@ public partial class HeaderControl : VerticalStackLayout
[AutoBindable(DefaultValue = "DateTime.Now", OnChanged = nameof(OnDateTimeChanged))]
private readonly DateTime? _birthDate;

[AutoBindable(DefaultValue = "USA")]
[AutoBindable(DefaultValue = "USA", ValidateValue = nameof(ValidateIsNullOrEmpty))]
private readonly string? _country;

[AutoBindable(ValidateValue = nameof(ValidateNotNull))]
private readonly string? _zipCode;

[AutoBindable]
private readonly string? _displayName;

Expand Down Expand Up @@ -48,11 +59,6 @@ private void UpdateDisplayName()
this.DisplayName = name.Trim();
}

private void UpdateDisplayName(string newValue)
{
// Do stuff here
}

private void UpdateDisplayName(string oldValue, string newValue)
{
// Do stuff here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class AutoBindableConstants

public const string AttrDefaultValue = "DefaultValue";

public const string AttrValidateValue = "ValidateValue";

public const string AttrDefaultBindingMode = "DefaultBindingMode";

public const string AttrHidesUnderlyingProperty = "HidesUnderlyingProperty";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public class AutoBindablePropertyGenerator : ISourceGenerator
private readonly List<Type> TypeImplementations = new() {
typeof(DefaultValue),
typeof(PropertyChanged),
typeof(DefaultBindingMode)
typeof(DefaultBindingMode),
typeof(ValidateValue)
};
private readonly List<IImplementation> Implementations = new();

Expand All @@ -38,6 +39,8 @@ public sealed class AutoBindableAttribute : Attribute
public string? DefaultBindingMode { get; set; }
public string? ValidateValue { get; set; }
public bool HidesUnderlyingProperty { get; set; } = false;
}
}";
Expand Down
Loading

0 comments on commit 83ebc57

Please sign in to comment.