0

I want to truncate the value of a data bound ObservableProperty in my program. It was my understanding that the OnXXXXXXChanging event (where XXXXXX is the variable name) is supposed to run before the actual value of the ObservableProperty is set.

For Example:

[ObservableProperty]
private string referenceNumber = string.Empty;

Then suppose regardless of what is entered, I want to trim the value of the ObservableProperty down to 10 characters at most. So I implement

partial void OnReferenceNumberChanging(string? oldValue, string newValue)
{
    if (newValue.Length > 10)
    {
        newValue = newValue.Substring(0, 10); 
    }
}

The challenge is that after this code runs and I interrogate the value of the ReferenceNumber ObservableProperty, it shows all the characters that were entered and not just the 10 the new value was trimmed down to. Am I missing something? Is this not an acceptable location to do this type of validation / modification?

2
  • When you mention "what is entered", how is this being done? For example an Entry control has the MaxLength property that would do this trimming up front. Is this option not available in your case? Commented Feb 3 at 23:35
  • So the bottom line is I know there are many ways to do this. I would like to do it in the event as described above so that if the value is changed from anywhere - including from other parts of the code - the value will be trimmed down and the work is all done in one central spot (In the event we need to increase the maximum length in the future.) Commented Feb 3 at 23:56

2 Answers 2

1

I usually let the event complete with the error, allowing the invalid input, but, schedule a post fix-up, e.g.

partial void OnReferenceNumberChanging(string? oldValue, string newValue)
{
    if (newValue.Length > 10)
    {
        Application.Current.MainPage.Dispatcher.Dispatch(() =>
        {
            ReferenceNumber = ReferenceNumber.Substring(0, 10);
        });
    }
}

This sort of validation is necessary, because .NET MAUI doesn't appear to have any obvious way of blocking invalid input at the time it occurs.

This pattern is needed for more complex fix-up such as regex pattern mask.

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah -- I thought changing the newValue was the correct thing to do but it appears I need to change the actual bound variable instead of the passed in values. I do wish they would change the newValue to a ref param so we could do this type of stuff by changing the newValue. :) Thanks
1

I agree that what you're trying to do seems reasonable but for it to work in that intuitive way the newValue argument would need to be passed by ref (and that isn't what it does).


So, as I understand it, you have two goals:

  • Limit the length of text that can be typed into the UI.
  • Limit the length of programmatic changes, too.

You may want to employ different strategies for each, because input to a control like Entry changes the visible text first and then invokes the bound property. The MaxLength property is your friend for this phase because it truncates the input text up front, so you don't get the flicker of the extra character while you react to it on the back end.

<Entry
    Text="{Binding ReferenceNumber}"
    Placeholder="Reference Number" 
    MaxLength="{Binding MaxLength}" />

Then, to limit the programmatic changes, the key would be to have a property that is observable (fires PropertyChanged events) but is not an [ObservableProperty].

partial class MainPageViewModel : ObservableObject
{
    public int MaxLength { get; } = 10;
    public string ReferenceNumber
    {
        get => _referenceNumber;
        set
        {
            if (value?.Length > MaxLength)
            {
                value = value.Substring(0, MaxLength);
            }
            if (!Equals(_referenceNumber, value))
            {
                _referenceNumber = value ?? string.Empty;
                OnPropertyChanged();
            }
        }
    }
    string _referenceNumber = string.Empty;
}

4 Comments

Yeah -- I see what you are saying about the newValue not being by reference. It makes sense. I am still going to use the Changing event as my screen gets input from multiple different locations (scanners, manual entry etc) so that location makes the most sense for me/
Understood, thx! I'm glad you've got a solution that works! I would like to point out that it's the difference between reacting to a property change then post-fixing it whereas this approach prevents it ever happening in the first place. Sometimes that matters and other times it doesn't.
Correct -- and we cannot control what the scanners are sending to the app as it is simply raw data. The application must determine which field the data is for and process it accordingly. The user can scan values into almost any field on the screen. If I were re-designing the system - I would do it differently. However, I have to work within what I have. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.