Непростое Решение для простой часто встречающейся задачи. Привязка TextBox к численному свойству [WPF, Элд Хасп] - C# WPF - Ответ 14899046

2) Причины проблемы. Внутренний механизм привязки.

Чтобы решить проблему, надо сначала понять её причину.

Для этого надо разобраться в механизме используемом привязками для присвоения значения свойствам.

Найди в документации мне это не удалось, пришлось разбираться в исходных кодах

класса BindingExpression

.

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

И как оказалось проблема лежит за пределами класса

BindingExpression

.

Для присваивания значения свойству источнику

BindingExpression

обращается к одному из способов рефлексии.

Используются, в порядке приоритета

:

PropertyDescriptor

,

PropertyInfo

,

DependencyProperty

и

DynamicPropertyAccessor

.

Как работает

PropertyDescriptor

я рассматривал в теме:

Разъяснение PropertyDescriptor: Почему в некоторых случаях Binding правильно работает без INPC (INotifyPropertyChanged)?

Механизм рефлексии при изменении значения свойства уведомляет об этом своих слушателей.

А так как присваивающая привязка тоже является слушателем, то она тоже срабатывает.

Привязка не может определить причину вызова: вызов был инициирован ею или нет.

Для этого ей просто не хватает информации.

Привязка получив число преобразует его в строковое представление и передаёт в

DependencyObject

для присвоения значения DP-свойству.

Если новое значение равно текущему, то присвоения не производится.

Теперь рассмотрим, что происходит при вводе числа с десятичной точкой и незначащими нулями:

Вводится число "123.000";
Срабатывает присвоение значения свойству источника (UpdateSource);
Для присвоения строка конвертируется в число 123.0;
Число передано в Рефлексию;
Рефлексия присваивает переданное число и вызывает привязку для обновления цели (UpdateTarget);
Привязка преобразует число 123.0 в строковое представление. И вот тут отбрасываются точка и незначащие нули! Из числа 123.0 получается строка "123";
Эта строка передаётся в DependencyObject для присвоения свойству Text. НО в свойстве Text строка "123.000". А так как она не равна строке "123", то свойству Text присваивается значение "123" - точка и нули пропали!

Для того чтобы присваивания не происходило надо сравнивать новое значение не просто с текущим, а оба значение преобразовать в численный тип свойства источника и сравнивать эти числа.

Но

DependencyObject

ничего "не знает" о привязках. Даже не знает есть ли они у этого свойства.

Для решения задачи необходимо сделать решение анализирующие текущее значение свойства

Text

ещё до преобразования числа в строку. И если из

Text

можно получить тоже число, то присваивания не должно происходить.

Вернуться к обсуждению:

Непростое Решение для простой часто встречающейся задачи. Привязка TextBox к численному свойству [WPF, Элд Хасп] C# WPF