Image


Кроме расширений и множества других вещей, в 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)


  1. JavaFox
    06.08.2016 19:28
    +2

    Спасибо! Рад, что несмотря на низкую популрнность Microsoft в хабр сообществе все равно появляются такие статьи. Будем тестить


  1. Pencroff
    06.08.2016 21:30

    acedened Как вы считаете на сколько перспективно изучать / оставаться с XAML и WPF? Его же можно применять только для Desktop приложний (этот рынок сокращается и все переходит в броузер) или где еще можно использовать XAML? Насколько я знаю Microsoft перестала развивать Silverlight, да и например Netflix перевел свой интерфейс на HTML5. А еще и приложения на базе Electron (тот же Slack) обладают необходимой функциональностью и производительностью.


    1. IL_Agent
      06.08.2016 21:35
      +1

      Здесь речь об uwp, а не wpf. Для последнего описанное в статье не актуально.


    1. acedened
      06.08.2016 21:35

      Кроме WPF, XAML используется ещё и в UWP и Xamarin. UWP подходит для разработки как и мобильных (Windows 10 Mobile), так и десктопных приложений, причем одновременно. Xamarin же позволяет разрабатывать приложения для Android, iOS и Windows Phone с довольно обширной общей кодовой базой, и это сейчас востребовано. На Xamarin спрос точно есть, а у UWP с этим хуже (у меня пока все на уровне личных проектов). А именно WPF остается только на десктопе. Насчёт перспектив не знаю, честно (но у WPF их, имхо, меньше всего из перечисленного мною).


      1. Pencroff
        06.08.2016 21:43

        Спасибо, не знал что в Xamarin можно использовать XAML для разных мобильных платформ.


  1. dmitry_dvm
    07.08.2016 10:06

    Привязка к методам только если методы в codebehind или непосредственно в классе, который x:DataType? Как-то всё это не по mvvm(


    1. acedened
      07.08.2016 11:07

      Которые непосредственно в классе. Т.е. можно например строку к верхнему регистру преобразовать.


      1. dmitry_dvm
        07.08.2016 12:27

        Ну это практически бесполезно, т.к. в классе можно просто завести свойство типа NameUpperCase => Name.ToUpper(); и будет то же самое, без лишних конструкций в разметке. Но, конечно, пусть лучше будет лишняя возможность привязки, мало ли когда пригодится.
        А вот привязка к статическим методам это интересно.


        1. synmcj
          07.08.2016 15:17

          > и будет то же самое, без лишних конструкций в разметке.

          Зато с лишними конструкциями в коде. И теперь ваш класс зачем-то знает, что вашей вьюхе нужно имя именно в upper-case. А потом у вас появятся ещё три вьюхи с другими требованиями, и вы на каждую будете создавать отдельное свойство в классе.

          Я предпочитаю такие вещи разруливать все-таки в разметке.


          1. dmitry_dvm
            07.08.2016 21:30

            А метод не в классе что ли будет? В вашем случае придется городить огород и в классе, и во вьюхе, а в моем — только в классе.


            1. acedened
              07.08.2016 21:32

              Метод будет у типа string, который просто вызывается с помощью биндинга


            1. synmcj
              08.08.2016 07:32

              Речь идет, конечно, о случаях, когда метод уже существует. Если нет — проблема решается конвертером.


    1. 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));
      
          }
      


      1. synmcj
        07.08.2016 15:21

        Почему просто не сделать так:

        public ViewModelType Vm => (ViewModelType)DataContext;
        


        1. IL_Agent
          07.08.2016 15:36

          Потому что DataContext может измениться.


          1. synmcj
            07.08.2016 15:55

            Да, возможно. Хотя признаться, я не часто использую UserControl, а контекст вьюх не меняется совсем, поэтому необходимости извращаться не чувствую.


  1. IL_Agent
    07.08.2016 12:55

    Принципиально нового ничего не добавили. Самое интересное, имхо — привязка к методам, которые теперь можно будет использовать вместо конверторов. Непонятно только, как TwoWay-binding будет работать? Bindback ведь только в обратную сторону работает, как я понял.
    Лучше б они поддержку MVVM улучшили…

    Каким образом эти нововведения связаны с апдейтом винды? Просто приурочены к нему, или приложение, написанное с новым SDK, не будет работать на необновленной винде?


    1. synmcj
      07.08.2016 15:40

      Да, новые фичи (помеченные звездочкой) требуют, чтобы в минимально поддерживаемой версии стоял билд 14393. Что, конечно, снижает полезность этих нововведений. В коде новые фичи можно обернуть в if (ApiInformation.IsTypePresent()), а вот что делать с XAMLом — непонятно.