Привязка данных WPF с помощью StringFormat, когда UpdateSourceTrigger имеет значение PropertyChanged

Я хочу, чтобы текстовое поле добавляло определенную строку, как только пользователь выходит из элемента управления, т.е. LostFocus, однако я предпочитаю, чтобы текстовое поле проверялось как пользовательские типы, поэтому UpdateSourceTrigger установлен в PropertyChanged,

Есть ли способ заставить это работать в WPF?

Посмотрел на этот вопрос, который похож, но интересно, есть ли более чистое решение?

Мой XAML это:

    <TextBox Text="{Binding Path=MyBindingPath, 
                            StringFormat='\{0} -HELLO',
                            TargetNullValue={x:Static sys:String.Empty},
                            ValidatesOnDataErrors=True,   
                            NotifyOnValidationError=True,    
                            UpdateSourceTrigger=PropertyChanged}"/>

2 ответа

Решение

Вы можете установить UpdateSourceTrigger на Explicit и в обработчике событий TextChanged TextBox вы можете явно вызывать UpdateSource после выполнения желаемых действий.

//write the code you want to run first and then the following code
BindingExpression exp = this.textBox1.GetBindingExpression(TextBox.TextProperty);
exp.UpdateSource();

Кажется, это самый чистый подход, который я придумал. По сути, это устанавливает события, которые отключают форматирование строки, когда пользователь фокусируется на текстовом поле, и восстанавливают формат строки, когда пользователь покидает текстовое поле.

      <TextBox Text="{Binding ValueToBind, UpdateSourceTrigger=PropertyChanged}" utilities:Formatting.StringFormat="N2" />
      public class Formatting
{
    public static readonly DependencyProperty StringFormatProperty = DependencyProperty.RegisterAttached("StringFormat", typeof(string), typeof(Formatting), new PropertyMetadata("", OnStringFormatPropertyChanged));

    private static void OnStringFormatPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is FrameworkElement element && e.OldValue != e.NewValue)
        {
            element.Loaded += (sender, args) =>
            {
                // Debug.Print("Loaded");
                UpdateStringFormat(element.IsFocused ? null : (string)e.NewValue, element);
            };
            element.LostFocus += (sender, args) =>
            {
                // Debug.Print("Lost Focus");
                UpdateStringFormat((string)e.NewValue, element);
            };
            element.GotFocus += (sender, args) =>
            {
                // Debug.Print("Got Focus");
                UpdateStringFormat(null, element);
            };
        }
    }

    private static void UpdateStringFormat(string stringFormat, FrameworkElement element)
    {
        var bindingExpression = element.GetBindingExpression(TextBox.TextProperty);
        if (bindingExpression != null && bindingExpression.ParentBinding != null)
        {
            Binding parentBinding = bindingExpression.ParentBinding;

            if (parentBinding.StringFormat == stringFormat)
                return;

            // Debug.Print("Updating String Format");
            bindingExpression.UpdateSource();

            Binding newBinding = new Binding
            {
                Path = parentBinding.Path,
                Mode = parentBinding.Mode,
                UpdateSourceTrigger = parentBinding.UpdateSourceTrigger,
                StringFormat = stringFormat
            };
            element.SetBinding(TextBox.TextProperty, newBinding);
        }
    }

    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static void SetStringFormat(DependencyObject obj, string stringFormat)
    {
        obj.SetValue(StringFormatProperty, stringFormat);
    }

    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static string GetStringFormat(DependencyObject obj)
    {
       return (string)obj.GetValue(StringFormatProperty);
    }
}
Другие вопросы по тегам