Dynamically change mask

7 posts, 1 answers
  1. Einar
    Einar avatar
    19 posts
    Member since:
    Jul 2014

    Posted 20 Mar 2015 Link to this post

    I'm trying to support a postal code textbox using the MaskedTextInput and was wondering if it was possible to databind to the mask property?

    The logic is so:
    1. Initially the textblock is blank so the mask would allow one number or letter.
    2. If the first digit entered is a letter we dynamically change the mask to Canadian postal code (A#A #A#)
    3. Otherwise it's a USA zip and the mask is #5

    Perhaps I'm making this too complicated and there's a way to supply a mask in the form of a regex that can accomplish this for me?

  2. Peshito
    Admin
    Peshito avatar
    497 posts

    Posted 23 Mar 2015 Link to this post

    Hi Einar,

    Actually you can achieve this scenario in two ways. The first one is to attach to the RadMaskedTextInput's ValueChanged event and update your mask depending on the value entered. The second way is MVVM one. Move the same logic you would have if you were using the ValueChanged event approach and call it in a property's setter of your ViewModel.

    Hope this helps.

    Regards,
    Peshito
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. UI for WPF is Visual Studio 2017 Ready
  4. Einar
    Einar avatar
    19 posts
    Member since:
    Jul 2014

    Posted 23 Mar 2015 in reply to Peshito Link to this post

    If I initially set the mask to a5 I can dynamically change it to #3 and l3 and it prevents the user from entering numbers or letters depending on the mask, however the masks text length doesn't change dynamically (I still see 5 _ characters). As expected you get some buggy behavior by typing in more than 3 characters when the control expects to only have 3.

    Additionally the value databinding doesn't appear to invoke the property setter when the value changes if the mask expects letters, but when I have it set to numbers I was notified every time I typed or deleted a number.

    Note that I am binding to the Value and Mask properties.
  5. Peshito
    Admin
    Peshito avatar
    497 posts

    Posted 24 Mar 2015 Link to this post

    Hello Einar,

    The databinding does not invoke the property setter on every letter typed when a mask is for instance like "A5". In this case the value is updated on every 5th symbol entered. This is how the control is designed and this behavior is expected. Using mask starting with small letter like "a5" however will invoke the setter on each input.

    As for the question about the dynamic change of the mask the scenario is complex and it is not supported out of the box as there are a lot of events and methods called after value is entered and in this specific scenario the Mask is being changed in a moment when not all calculations are made. In order to workaround this, a Dispatcher can be used after attaching to the ValueChanged event. This is approach is shown in the attached sample project.
    private void tbClid_ValueChanged(object sender, Telerik.Windows.RadRoutedEventArgs e)
    {
        var value = (sender as RadMaskedTextInput).Value;
        if (value.ToString().StartsWith("3"))
        {
            ChangeMaskDispatched("#3");
        }
        else if (value.ToString().StartsWith("5"))
        {
            ChangeMaskDispatched("#5");
        }
    }
    private void ChangeMaskDispatched(string newMASK)
    {
        Dispatcher.BeginInvoke(new Action(() => tbClid.Mask = newMASK));
    }


    Regards,
    Peshito
    Telerik
     

    See What's Next in App Development. Register for TelerikNEXT.

     
  6. Einar
    Einar avatar
    19 posts
    Member since:
    Jul 2014

    Posted 24 Mar 2015 in reply to Peshito Link to this post

    Peshito,

    Thanks for the code example. it seems to work fairly well. However, we run into issues when switching between masks.

    I've added a condition to your code that says "if the value is null or empty then reset the mask" (so that I can allow the user to switch back and forth between the masks). It correctly works if I enter 3 numbers, backspace them all out and then the mask changes to "#5", however once the mask changes the control stops reporting its value changed on each character change and therefore when I backspace all the characters out in the second mask I don't hit the condition to reset the mask once again.

    Note that in my specific use case I start with an alpha numeric mask and then conditionally switch to an all numeric or alphanumeric mask based on a Canadian postal code. (L1#1L1 #1L1#1)

            private string _lastVal;
            private void RadMaskedInputBase_OnValueChanged(object sender, RadRoutedEventArgs e)
            {
                var control = (sender as RadMaskedTextInput);
                var value = control.Value;

                //Cache the last value as resetting the mask at the wrong time causes issues
                if (string.IsNullOrWhiteSpace(value) && !string.IsNullOrWhiteSpace(_lastVal))
                {
                    ChangeMaskDispatched("a5");
                    _lastVal = value;
                    return;
                }

                if (Char.IsNumber(value[0]))
                {
                    ChangeMaskDispatched("#5");
                }
                else if (Char.IsLetter(value[0]))
                {
                    ChangeMaskDispatched("L1#1L1 #1L1#1");
                }

                _lastVal = value;
            }

            private void ChangeMaskDispatched(string newMASK)
            {
                Dispatcher.BeginInvoke(new Action(() => PostalCodeMasked.Mask = newMASK));
            }



  7. Answer
    Peshito
    Admin
    Peshito avatar
    497 posts

    Posted 25 Mar 2015 Link to this post

    Hi Einar,

    I am glad the workaround worked well.

    As for the last issue you hit with being unable to attach to ValueChanged event in this scenario, it is actually expected. This is so, because the ""L1#1L1 #1L1#1" is required mask where empty strings or null values are invalid for this type of mask. The RadMaskedTextInput exposes a property called AllowInvalidValues. Setting it to True will allow you to enter the invalid symbol and therefore it will fire the ValueChanged event. I just tried it using the code snipped you shared and it worked well.

    Regards,
    Peshito
    Telerik
     

    See What's Next in App Development. Register for TelerikNEXT.

     
  8. Einar
    Einar avatar
    19 posts
    Member since:
    Jul 2014

    Posted 25 Mar 2015 in reply to Peshito Link to this post

    Peshito,

    AllowInvalidValues was indeed the missing piece to this. Thanks so much for your help!
Back to Top
UI for WPF is Visual Studio 2017 Ready