Привязка данных 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);
}
}