-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbinding.txt
More file actions
56 lines (47 loc) · 7.43 KB
/
binding.txt
File metadata and controls
56 lines (47 loc) · 7.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Связывание данных.
Связывание данных - процедура автоматической синхронизации между объектом-источником и объектом-приёмником.
В качестве источника и приёмника могут выступать любые объекты. Ограничения, накладываемые на то, какими должны
быть объекты, зависят от выбранного направления связывания. Если используется двунаправленный байндинг, то
оба объекта должны реализовывать интерфейс INotifyPropertyChanged. Если данные идут в одну сторону (
режим OneWay или OneWayToSource), то INotifyPropertyChanged должен реализовывать тот класс, который выступает
в роли поставщика данных (если режим OneWay, то данные бегут от источника к приемнику, и источник должен
реализовывать INotifyPropertyChanged, в случае OneWayToSource - всё наоборот). UI классы мы не можем заставить
реализовывать этот интерфейс, но эта проблема обходится путём написания адаптеров для каждого
поддерживаемого UI класса. При этом UI классы могут быть только приёмником (Target).
Конвертирование значений.
При настройке связывания часто бывает ситуация, когда поле в классе источнике - одного типа (например, строка),
а поле класса-приёмника - другого ( целое число). В этом случае нам помогут конверторы. Опять же, для основных
пар типов такие конверторы уже написаны, но добавить свой собственный тоже не проблема. Для этого нужно
реализовать интерфейс IBindingConverter и зарегистрировать его в BindingSettings вызовом addConverter().
Правила и ограничения, связанные с поддержкой синхронизации коллекций.
Коллекции, которые не реализуют интерфейс IObservableList, синхронизируются обычным образом.
То есть берётся ссылка из свойства одного объекта и передаётся в другой. При этом могут даже быть вызваны
конвертеры, если такие присутствуют (например, можно сделать такой конвертер для преобразования
массива строк в список и наоборот). Если же свойство класса реализует IObservableList, то в сценариях, когда
данные идут из этого объекта, будет использован алгоритм синхронизации коллекций. Он работает следующим образом:
при нотификации об изменении свойства (через INotifyPropertyChanged) выполняется подписка на эту коллекцию, и
в обработчиках изменения переносятся автоматически в список другого объекта. При этом коллекции перед подпиской
синхронизируются - коллекция-приёмник очищается и заполняется элементами коллекции-источника. Ограничение при использовании
observables следующее: если вы используете IObservableList, то с другой стороны должен быть класс,
реализующий IList. Если же вам нужен TwoWay-байндинг, то оба свойства должны быть IObservableList
и реализовывать IList. Отметим, что необходима реализация именно непараметризованного IList.
Коллекции, реализующие только IList<T>, но не реализующие IList, не могут быть
приёмниками изменений (но в дотнете таких коллекций я не нашёл, а ObservableList и ObservableList<T> реализуют
оба интерфейса, по аналогии с тем, как выполнены стандартные .NET-классы List<T> и Collection<T>).
Как выбираются конвертеры для сценариев с observable list'ами ?
Никак. Если на стороне, с которой ожидаются данные, лежит IObservableList, то на другой стороне обязан быть IList.
Сами элементы коллекций не конвертируются, если типы разные - синхронизация завершится ошибкой.
Но если на стороне, с которой ожидаются данные, будет лежать нечто, не являющееся IObservableList, то конвертеры
будут применяться как обычно, несмотря на то, что с другой стороны может быть IObservableList. В этом варианте
конвертеры могут применяться уже не к элементам коллекции, а к коллекциям целиком. Всё зависит от
режима байндинга, то есть того, откуда и куда будут поступать данные - от Source к Target, или наоборот, или в
обе стороны.
Валидация значений.
Валидация работает только в сторону Target -> Source, поскольку UI элементы у нас всегда в роли Target.
Валидация отрабатывает только после успешной конвертации значений. Если конвертер не смог сконвертировать
значение, валидатор вызван не будет, а в качестве BindingResult вы увидите ConversionError с сообщением
об ошибке. Чтобы написать собственный валидатор, достаточно реализовать интерфейс IBindingValidator.
Регистрировать в BindingSettings его не нужно, достаточно установить его для инстанса Binding:
binding.setValidator(validator). Чтобы узнать результат конвертации и валидации, нужно подписаться на
событие инстанса Binding setBindingResultListener(); Обработчик будет вызываться каждый раз при срабатывании
связывания. Для ObservableList валидаторы не вызываются.