jaydopartu
jaydopartu

Reputation: 93

MAUI.NET update binding on lost focus alike

introduction:

Using MAUI.NET with MVVM architecture, but MVVM can be sacrifice (this need is so important for the application). Standard way - I have ViewModel with a property with get and set implementing INotifyPropertyChanged and binded this one to the Text property of the Entry in the Views that have BindingContext of the mentioned ViewModel.

need:

Need binding to be executed (set property called) after the user go out of the Entry (click somewhere outside of the control or push TAB on keyboard). Default binding situation is that the binding is executed every keystroke the user do.

example:

If the user enters Entry and make input 1234 the set funciton on binded property in VM is fired 4 times, after every key pushed. I want it to fire just once after user ends with this Entry control.

tries:

Seems to be so basic... I already tried:

EDIT: my workaround:

I have managed to do crazy workaround like that:

Upvotes: 0

Views: 1983

Answers (1)

Sir Rufo
Sir Rufo

Reputation: 19096

You can write a behavior for this as described in the MAUI documentation.

In this behavior you declare an attached property for the binding with your ViewModel and subscribe to the Unfocused event of the entry to update the attached property.

public class EntryLostFocusBehavior : Behavior<Entry>
{
    public static readonly BindableProperty TextProperty = BindableProperty.CreateAttached(
        "Text",
        typeof( string ),
        typeof( EntryLostFocusBehavior ),
        null,
        BindingMode.TwoWay,
        propertyChanged: TextPropertyChanged );

    public static string GetText( Entry entry ) => (string)entry.GetValue( TextProperty );
    public static void SetText( Entry entry, string value ) => entry.SetValue( TextProperty, value );

    private static void TextPropertyChanged( BindableObject bindable, object oldValue, object newValue )
    {
        var entry = (Entry)bindable;
        entry.Placeholder = newValue as string;
    }

    protected override void OnAttachedTo( Entry bindable )
    {
        base.OnAttachedTo( bindable );
        bindable.Unfocused += Entry_Unfocused;
    }

    protected override void OnDetachingFrom( Entry bindable )
    {
        base.OnDetachingFrom( bindable );
        bindable.Unfocused -= Entry_Unfocused;
    }

    private void Entry_Unfocused( object sender, FocusEventArgs e )
    {
        var entry = (Entry)sender;
        SetText( entry, entry.Text );
    }
}

and use this in your view

<Page ...
      xmlns:b="clr-namespace:MyMauiApp.Behaviors"
      ...>

  <Entry b:EntryLostFocusBehavior.Text="{Binding Value1}">
      <Entry.Behaviors>
          <b:EntryLostFocusBehavior />
      <Entry.Behaviors>
  </Entry>

  <Entry b:EntryLostFocusBehavior.Text="{Binding Value2}">
      <Entry.Behaviors>
          <b:EntryLostFocusBehavior />
      <Entry.Behaviors>
  </Entry>

</Page>

And thats it for the view/viewmodel. No code-behind, no additional properties.

Upvotes: 3

Related Questions