xamarin / XamarinCommunityToolkit

The Xamarin Community Toolkit is a collection of Animations, Behaviors, Converters, and Effects for mobile development with Xamarin.Forms. It simplifies and demonstrates common developer tasks building iOS, Android, and UWP apps with Xamarin.Forms.
MIT License
1.58k stars 471 forks source link

[Bug] RequiredStringValidationBehavior stays invalid when it should be valid #1969

Open CostasAthan opened 1 year ago

CostasAthan commented 1 year ago

Description

RequiredStringValidationBehavior stays always invalid

Steps to Reproduce

StackLayout myLayout = new StackLayout
{ 
    Children =
    {
        new Entry(),

        new Entry(),

        new Entry()
    }
};

myLayout.Children.OfType<Entry>().ElementAt(2).Behaviors.Add
(
     new RequiredStringValidationBehavior
      {
           RequiredString = myLayout.Children.OfType<Entry>().ElementAt(1).Text,
           InvalidStyle = invalidEntryStyle,
           Flags = ValidationFlags.ValidateOnValueChanging
      }
);

Expected Behavior

  1. Run the aforementioned code.
  2. Enter the same strings in both the second and the third Entries.

Actual Behavior

The RequiredStringValidationBehavior stays invalid

Basic Information

FedericoNembrini commented 1 year ago

I think you are not properly binding RequiredString.

At the moment you are setting RequiredString with the current value of myLayout.Children.OfType<Entry>().ElementAt(1).Text.

You should do something like this:

requiredStringValidationBehaviorReference
.SetBinding(
    RequiredStringValidationBehavior.RequiredStringProperty,
    new Binding("Text", source: myLayout.Children.OfType<Entry>().ElementAt(1))
);

For reference: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/basic-bindings#bindings-without-a-binding-context

CostasAthan commented 1 year ago

At the moment you are setting RequiredString with the current value of myLayout.Children.OfType().ElementAt(1).Text

Yes. Isn't RequiredString the string that will be compared to the value provided in the third entry? When both the second and the third entries have as a value exactly the same string, shouldn't the above code return a valid state for the third one?

FedericoNembrini commented 1 year ago

When you are executing this?

myLayout.Children.OfType<Entry>().ElementAt(2).Behaviors.Add
(
     new RequiredStringValidationBehavior
      {
           RequiredString = myLayout.Children.OfType<Entry>().ElementAt(1).Text,
           InvalidStyle = invalidEntryStyle,
           Flags = ValidationFlags.ValidateOnValueChanging
      }
);

myLayout.Children.OfType<Entry>().ElementAt(1).Text is already set with the desired value? Otherwise, you are setting RequiredString to string.Empty, and since you are not binding the value, even if you change the text of the second entry, RequiredString will remain string.Empty.

CostasAthan commented 1 year ago

@FedericoNembrini

Yes, I got what you are saying!

Should the following version work though?

myLayout.Children.OfType<Entry>().ElementAt(2).Behaviors.Add
(
     new RequiredStringValidationBehavior
      {
           RequiredString = myLayout.Children.OfType<Entry>().ElementAt(1).Text,
           InvalidStyle = invalidEntryStyle,
           Flags = ValidationFlags.ValidateOnValueChanging,
           BindingContext = myLayout.Children.OfType<Entry>().ElementAt(1).Text
      }
)

It doesn't work either.

FedericoNembrini commented 1 year ago

No, it cannot work. You have to set the binding with .SetBinding()

CostasAthan commented 1 year ago

What's the purpose of BindingContext property then?

FedericoNembrini commented 1 year ago

You need to learn more about Binding and BindingContext. In simple terms the BindingContext is the object it is associated with. However, the fact remains that to tell RequiredString what property to "Bind" to, you must use SetBinding().