Кроме расширений и множества других вещей, в Anniversary Update сильно расширили возможности компилируемых привязок (x:Bind). Давайте посмотрим, что изменилось.
Звездочкой (*) будут помечены возможности, требующие нового SDK.
Коллекции
Теперь вы можете использовать синтаксис вида {x:Bind Collection[0]}
, чтобы привязываться к определенным элементам списка. Более того, если исходный список реализует INotifyCollectionChanged, а Mode установлен в OneWay или TwoWay, привязка будет обновляться при изменении списка (даже если изменение не затрагивает привязанный элемент). Для использования этой возможности список должен реализовывать IList<T>
или IVector<T>
.
Такой синтаксис доступен не только для списков, но также для словарей и Map'ов — {x:Bind Dictionary['Key']}
. Правда типом ключа может быть только string. Аналогично спискам, словарь или Map может реализовывать IObservableMap для обновления привязок. Для экранирования кавычек в строке используется символ ^.
Attached Properties
Появилась возможность привязываться к значениям Attached Properties. Например, {x:Bind MyButton.(Grid.Row)}
привяжется к номеру строки, в которой находится MyButton. Если Attached Property не объявлена в стандартном пространстве имен, вам нужно добавить соответствующий префикс с указанием нужного namespace.
Преобразования*
В отличие от классического Binding, x:Bind строго типизирован, и невалидные привязки выдают ошибки в compile-time. Но бывает так, что вы привязываетесь к свойству с каким-то объявленным типом, но само свойство является объектом более конкретного типа. И даже если вы уверены, что член, которого нет в базовом типе, есть в его наследнике, просто так привязаться к этому члену вы не сможете. Для решения этой проблемы в 1607 добавили возможность кастинга — {x:Bind ((MyObject) Property).Member}
или {x:Bind Property.(MyObject.Member)}
(рекомендуется первый вариант). Это также бывает полезно для преобразования nullable в обычный тип (например, bool? -> bool).
BooleanToVisiblityConverter*
Теперь не нужен. Булевые значения будут неявно конвертироваться в Visibility. Наконец-то.
Привязка к функциям*
Это, пожалуй, самая мощная новая возможность x:Bind. Теперь вы можете привязываться непосредственно к возвращаемым значениям функций. Например, {x:Bind MyNumber.ToString('F4')}
будет возвращать MyNumber с 4 знаками после запятой.
- В качестве аргументов вы можете передавать числа, строки, булевые значения (x:True и x:False), null (x:Nul) и пути к вашим свойствам. К тому же, если Mode установлен в OneWay или TwoWay, привязка будет обновляться при изменении аргументов.
- Вы можете привязываться и к статическим методам, используя нотацию
пространствоимен:Класс.Метод
. - Для использования TwoWay-привязки вам потребуется указать BindBack. Эта функция будет вызываться при изменении значения в пользовательском интерфейсе, и она должна принимать один аргумент (новое значение). Пример —
{x:Bind MyFunction(MyProperty), BindBack=Update}
Разумеется, есть ограничения:
- Функция должна быть доступна в месте вызова
- Перегрузка выполняется по количеству, а не типам аргументов. То есть, выбрана будет первая функция, имеющая подходящее количество аргументов.
- Передаваемые типы должны точно совпадать с принимаемыми.
- Возвращаемый тип должен точно совпадать с значением свойства, к которому идет привязка.
Как мы видим, XAML, хоть и неспешно, но развивается, что очень радует. Вполне возможно, что в RS2 и RS3 тоже добавят что-нибудь новое. А пока можно потихоньку осваивать новые вещи и избавляться от ненужного теперь кода.
Комментарии (18)
Pencroff
06.08.2016 21:30acedened Как вы считаете на сколько перспективно изучать / оставаться с XAML и WPF? Его же можно применять только для Desktop приложний (этот рынок сокращается и все переходит в броузер) или где еще можно использовать XAML? Насколько я знаю Microsoft перестала развивать Silverlight, да и например Netflix перевел свой интерфейс на HTML5. А еще и приложения на базе Electron (тот же Slack) обладают необходимой функциональностью и производительностью.
IL_Agent
06.08.2016 21:35+1Здесь речь об uwp, а не wpf. Для последнего описанное в статье не актуально.
acedened
06.08.2016 21:35Кроме WPF, XAML используется ещё и в UWP и Xamarin. UWP подходит для разработки как и мобильных (Windows 10 Mobile), так и десктопных приложений, причем одновременно. Xamarin же позволяет разрабатывать приложения для Android, iOS и Windows Phone с довольно обширной общей кодовой базой, и это сейчас востребовано. На Xamarin спрос точно есть, а у UWP с этим хуже (у меня пока все на уровне личных проектов). А именно WPF остается только на десктопе. Насчёт перспектив не знаю, честно (но у WPF их, имхо, меньше всего из перечисленного мною).
Pencroff
06.08.2016 21:43Спасибо, не знал что в Xamarin можно использовать XAML для разных мобильных платформ.
dmitry_dvm
07.08.2016 10:06Привязка к методам только если методы в codebehind или непосредственно в классе, который x:DataType? Как-то всё это не по mvvm(
acedened
07.08.2016 11:07Которые непосредственно в классе. Т.е. можно например строку к верхнему регистру преобразовать.
dmitry_dvm
07.08.2016 12:27Ну это практически бесполезно, т.к. в классе можно просто завести свойство типа NameUpperCase => Name.ToUpper(); и будет то же самое, без лишних конструкций в разметке. Но, конечно, пусть лучше будет лишняя возможность привязки, мало ли когда пригодится.
А вот привязка к статическим методам это интересно.synmcj
07.08.2016 15:17> и будет то же самое, без лишних конструкций в разметке.
Зато с лишними конструкциями в коде. И теперь ваш класс зачем-то знает, что вашей вьюхе нужно имя именно в upper-case. А потом у вас появятся ещё три вьюхи с другими требованиями, и вы на каждую будете создавать отдельное свойство в классе.
Я предпочитаю такие вещи разруливать все-таки в разметке.dmitry_dvm
07.08.2016 21:30А метод не в классе что ли будет? В вашем случае придется городить огород и в классе, и во вьюхе, а в моем — только в классе.
synmcj
08.08.2016 07:32Речь идет, конечно, о случаях, когда метод уже существует. Если нет — проблема решается конвертером.
IL_Agent
07.08.2016 13:01Да, это главная проблема x:Bind. Приходится извращаться как-то так
public partial class MyView : UserControl { public MyView() { this.InitializeComponent(); DataContextChanged += OnDataContextChanged; } private void OnDataContextChanged(Windows.UI.Xaml.FrameworkElement sender, Windows.UI.Xaml.DataContextChangedEventArgs args) { ViewModel = DataContext as ViewModelType } public ViewModelType ViewModel { get { return (ViewModelType)GetValue(ViewModelProperty); } set { SetValue(ViewModelProperty, value); } } public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register("ViewModel", typeof(ViewModelType), typeof(ownerclass), new PropertyMetadata(0)); }
synmcj
07.08.2016 15:21Почему просто не сделать так:
public ViewModelType Vm => (ViewModelType)DataContext;
IL_Agent
07.08.2016 12:55Принципиально нового ничего не добавили. Самое интересное, имхо — привязка к методам, которые теперь можно будет использовать вместо конверторов. Непонятно только, как TwoWay-binding будет работать? Bindback ведь только в обратную сторону работает, как я понял.
Лучше б они поддержку MVVM улучшили…
Каким образом эти нововведения связаны с апдейтом винды? Просто приурочены к нему, или приложение, написанное с новым SDK, не будет работать на необновленной винде?
synmcj
07.08.2016 15:40Да, новые фичи (помеченные звездочкой) требуют, чтобы в минимально поддерживаемой версии стоял билд 14393. Что, конечно, снижает полезность этих нововведений. В коде новые фичи можно обернуть в if (ApiInformation.IsTypePresent()), а вот что делать с XAMLом — непонятно.
JavaFox
Спасибо! Рад, что несмотря на низкую популрнность Microsoft в хабр сообществе все равно появляются такие статьи. Будем тестить