Skip to content

[Backport to preview2] Fix empty string binding to nullable value types#34243

Closed
StephaneDelcroix wants to merge 1 commit intorelease/11.0.1xx-preview2from
backport/33536-preview2
Closed

[Backport to preview2] Fix empty string binding to nullable value types#34243
StephaneDelcroix wants to merge 1 commit intorelease/11.0.1xx-preview2from
backport/33536-preview2

Conversation

@StephaneDelcroix
Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Backport of #33536 to release/11.0.1xx-preview2.

Cherry-pick of 4cc0dc5 — clean, no conflicts.

> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Description

When binding `Entry.Text` to a nullable value type property (e.g.,
`int?`), clearing the Entry now correctly sets the property to `null`
instead of retaining the previous value.

## Issue

Fixes #8342

## Root Cause

In `BindingExpressionHelper.TryConvert()`, when converting an empty
string to a nullable type like `int?`:
1. The underlying type was extracted (`int`)
2. `Convert.ChangeType("", int)` was called, which throws
`FormatException`
3. The catch block returned `false`, keeping the old value

## Solution

Added a check before `Convert.ChangeType()` to handle empty/whitespace
strings when converting to nullable types. When the target type is
nullable and the source is an empty/whitespace string, the value is set
to `null` and the conversion succeeds.

## Behavior

| Target Type | Empty String Input | Result |
|-------------|-------------------|--------|
| `int?`, `double?`, etc. (nullable) | `""` | `null` ✅ |
| `int`, `double`, etc. (non-nullable) | `""` | Conversion fails,
retains last valid value (unchanged) |

## Testing

Added two unit tests in `BindingUnitTests.cs`:
- `TwoWayBindingToIntPropertyWithEmptyStringRetainsLastValidValue` -
Verifies non-nullable int behavior
- `TwoWayBindingToNullableIntPropertyWithEmptyStringBecomesNull` -
Verifies nullable int now converts to null
Copilot AI review requested due to automatic review settings February 25, 2026 13:05
@StephaneDelcroix StephaneDelcroix added this to the .NET 11.0-preview2 milestone Feb 25, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Backports the binding conversion fix to release/11.0.1xx-preview2 so that clearing an Entry.Text bound TwoWay to a nullable value type (e.g., int?) correctly updates the source to null instead of retaining the previous value.

Changes:

  • Update BindingExpressionHelper.TryConvert to treat "" as null when converting to nullable value types.
  • Add unit tests covering TwoWay bindings to non-nullable and nullable numeric properties when the Entry text is cleared (and related scenarios).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/Controls/src/Core/BindingExpressionHelper.cs Adds an early-return conversion path mapping empty string to null for nullable target types.
src/Controls/tests/Core.UnitTests/BindingUnitTests.cs Adds regression tests for clearing Entry.Text when bound to int, int?, and double?.

var entry = new Entry { BindingContext = vm };
entry.SetBinding(Entry.TextProperty, "Value", BindingMode.TwoWay);

Assert.Equal("3.14", entry.Text);
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test hard-codes the decimal separator by asserting entry.Text equals "3.14". Since binding/string conversion uses CultureInfo.CurrentCulture, this can fail under cultures that use a comma decimal separator (e.g., pt-PT/de-DE). Set the culture explicitly for the test (e.g., InvariantCulture) or compute the expected string using the current culture (e.g., 3.14.ToString(CultureInfo.CurrentCulture)).

Suggested change
Assert.Equal("3.14", entry.Text);
Assert.Equal(3.14.ToString(CultureInfo.CurrentCulture), entry.Text);

Copilot uses AI. Check for mistakes.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants