9
votes
    <!-- View -->
    <TextBox Text="{Binding str, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

    // View Model
    private string _str;
    public string str
    {
        get { return _str; }
        set
        {
            if (!value.Contains("a"))
                _str = value;

            OnPropertyChanged(nameof(str));
        }
    }

When typing in the TextBox I want it to throw out any invalid characters (in this sample case the letter 'a', but it could really be for anything). For example:

  1. User types 'fds' followed by an 'a'
  2. str detects a, so it doesn't set _str to 'fdsa', keeping it at 'fds' but raises the event anyway to indicate to the view to throw out the 'a'.
  3. In WPF, this results in the textbox containing 'fds'. In UWP, this results in the textbox incorrectly containing 'fdsa' still.

It appears that in UWP when a control has focus, it will not respect the TwoWay binding.

I can create a button that has a Click event that when pressed will update my TextBox correctly.

    private void btn_Click(object sender, RoutedEventArgs e)
    {
        OnPropertyChanged(nameof(str));
    }

We have many ViewModels that we need to use in both WPF and UWP views, and we have this required behavior all over the place. What is a good solution to this problem?

* EDIT *

Came back to the problem after the weekend and it seems to have fixed itself. I have no idea why. I am closing the question for now.

1
I think is a kind of problem related of UWP, I see a lot of people complaining about two way binding on uwp, I did a test here on a desktop application and works fine. Maybe a converter can help you. - Bruno Joaquim
I find this always works well as long as I explicitly set UpdateSourceTrigger=PropertyChanged - Saxar
Did you ever figure out why this happened? I'm having this issue. - user3007447

1 Answers

1
votes

You could use a converter to solve your problem, you could elaborate a better converter, in my example I just use a silly converter to demonstrate my idea.

Converter:

 public class Converter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            var someString = value.ToString();
            return someString.Replace("a", "");
        }

        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }
}

XAML

<TextBox Text="{Binding Str, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource converter}}"/>

You could use an attached behavior also.