Разработка кроссплатформенных мобильных приложений в Delphi #4

    Разработка кроссплатформенных мобильных приложений в DelphiЧасть #1
    Часть #2
    Часть #3

    В четвертой части настоящего цикла мы вновь возвратимся к разработке «настольного» приложения и попытаемся более подробно разобраться с технологией связывания объектов LiveBinding. Данный механизм универсален и подходит как для мобильных, так и настольных приложений. Более того, этот механизм работает и в VCL. Знакомство же с LiveBinding лучше начать именно в классическом проекте.

    Прежде всего, нам придется выполнить несколько однотипных задач, работа над которыми может показаться рутинной. Речь идет о создании форм редактирования списков, а именно, списка единиц измерений и списка продуктов. Данные формы будут вызываться из меню главной формы, которое нам также предстоит создать.

    Итак, в модуле данных поместим два компонента TFDTable и настроим их на работу с таблицами tblUnit и tblFoodstuff (по аналогии с набором данных для работы с таблицей tblRecipe). Двойным щелчком на компоненте откроем редактор полей, добавим все поля (пункт контекстного меню Add all fields).

    Важно понимать, что практически во всех реализациях компоненты наборов данных наследуются от класса TDataSet и работают с некоторым набором полей. Здесь имеются в виду экземпляры классов, наследников TField (TIntegerField, TStringField и т.д.). Набор полей можно создать в режиме проектирования (design-time) и настроить свойства полей с помощью «инспектора объектов». Если рассматривать TFDTable, то помимо полей, соответствующих физическим полям таблицы, можно создать и другие типы полей, например, вычисляемое (Caclulated) или подставляемое (LookUp) поле. Значения этих полей будут вычисляться динамически в ходе работы программы, а не браться из источника данных. Чуть ниже мы рассмотрим пример создания таких полей.

    В том же случае, если набор полей не создан в режиме проектирования, при открытии набора данных в процессе работы программы, набор полей будет создан автоматически.

    Ниже приведен фрагмент файла формы модуля данных uDM.dfm, содержащий описание одного из наборов данных и связанных с ними полей. Текстовое представление формы можно получить, если в контекстном меню формы выбрать пункт «View as Text». Для того, что бы вернуться в обычный режим представления формы, следует нажать «View as Form».

      object FDTUnits: TFDTable
        IndexFieldNames = 'Id'
        Connection = FDConnection1
        UpdateOptions.UpdateTableName = 'tblUnit'
        TableName = 'tblUnit'
        Left = 112
        Top = 208
        object FDTUnitsId: TFDAutoIncField
          FieldName = 'Id'
          Origin = 'Id'
          ProviderFlags = [pfInWhere, pfInKey]
          ReadOnly = True
        end
        object FDTUnitsUnitName: TStringField
          FieldName = 'UnitName'
          Origin = 'UnitName'
          Required = True
          Size = 25
        end
        object FDTUnitsAbbr: TStringField
          FieldName = 'Abbr'
          Origin = 'Abbr'
          Required = True
          Size = 7
        end
      end
    
    


    Созданные наборы данных, необходимо открыть при запуске программы. Модифицируем процедуру ConnectToDB следующим образом:

    function TDM.ConnectToDB: Boolean;
    begin
      try
        FDConnection1.Connected := True;
        FDTRecipe.Open;
        FDTUnits.Open;
        FDTFoodstuff.Open;
    
      except
    
      end;
      Result := FDConnection1.Connected;
    end;
    


    Следующим шагом разработки приложения станет создание новой формы для отображения и редактирования таблицы (списка) единиц измерения. Естественно, это будет FM HD форма. Значение свойства Position установим как poMainFormCenter, для того, что бы данная форма отображалась посредине главной формы.

    В список используемых модулей секции implementation добавим модуль данных:

    implementation
    
    {$R *.fmx}
    
    uses uDM;
    


    Поместим на форме компоненты TGrid, TPanel. На панели поместим кнопку, поле ввода и метку TLabel, как это показано на рисунке. Единственное назначение кнопки – закрыть форму. Свойству ModalResult определим значение mrOk.

    Мы сохраняем названия визуальных компонентов по умолчанию исключительно из соображений наглядности. В рабочих проектах, естественно, их лучше переименовать.

    FireMonkey форма

    С помощью редактора LiveBinding свяжем визуальные компоненты с источниками данных. В самых общих чертах, LiveBinding это механизм, позволяющий связывать свойства различных объектов, но не при помощи жёсткой ссылочной компилированной связи, а на основе гибких выражений (expressions). Механизм LiveBindings базируется на шаблоне «наблюдатель» (observer). Так, изменение некоторого свойства объекта А, с помощью LiveBinding может повлечь за собой изменение свойства объекта Б. Связи между объектами могут быть однонаправленными и двунаправленными. Такой подход очень удобно использовать для отображения данных из наборов данных. Фактически, если в стандартном подходе VCL для отображения данных из таблиц требовались специальные DB-ориентированные (DB-Aware) визуальные компоненты, то LiveBindings позволяет использовать для этой цели самые обычные элементы управления («контролы). Более того, визуальные компоненты не требуют специальной подготовки, для работы с LiveBindings. Преимущество такого подхода очевидно. Давайте рассмотрим данный процесс чуть внимательнееболее подробно.

    Итак, откроем LiveBinding Designer и найдем элемент, соответствующий набору данных, FDTUnits. Если элементы из модуля данных не отображаются в LiveBinding дизайнере, то следует сделать обновление (в контекстном меню выбрать пункт Refresh Designer). Попытаемся связать значение свойства Text поля ввода Edit1 со значением поля UnitName в наборе данных. Используем обычное перетаскивание (drag-n-drop).

    LiveBinding Designer

    Что же произошло на самом деле?

    Помимо того, что в дизайнере визуально отобразилась связь, на форме появилось два новых не визуальных компонента. Компонент TBindSourceDB с помощью свойства DataSet осуществляет связь с исходным набором данных (в нашем случае DM.FDTUnits). Обратите внимание на то, что как только была установлена связь между свойством визуального компонента и полем, в LiveBinding дизайнере объект DM.FDTUnits оказался вложенным в новый объект BindSourceDB1, и этот объект появился на форме.

    LiveBinding

    Нетрудно догадаться, какое значение свойства DataSet будет у данного объекта. Для тех, кто мыслит в терминах «классической VCL разработки», проще всего воспринимать TBindSourceDB как некий аналог TDataSource. Вы можете точно также «бросить» этот компонент на форму и указать значение свойства DataSet. А затем «привязать» к нему контрол. Только теперь это будет не специальный DB-контрол, а любой визуальный компонент. А, следовательно, вы должны указать, какое именно свойство компонента и каким образом должно отображать (и, возможно, изменять) данные из набора данных. Давайте посмотрим, как это сделать.

    Кроме BindSourceDB1 на форме появился и еще один объект — BindingsList1. Он является хранилищем для всех связей между объектами. Связи эти могут быть разных типов. Как видно из рисунка, в нашем случае в BindingsList была добавлена связь типа TLinkControlToField.

    FireMonkey LiveBinding. Редактор связей

    Вы можете отредактировать ее свойства, например, сделать связь не двунаправленной, а однонаправленной.

    Oblect inspector

    Если вы попробуете добавить новую связь, то увидите, что существует довольно много различных типов связей, практически позволяющих связать «всё со всем».

    Дерево объектов. BindingsList

    Теперь свяжем Grid и BindNavigator с набором данных. Для компонента BindNavigator достаточно задать свойство DataSource. При этом в списке связей BindingsList1 новая связь не создается. А вот при связывании Grid’а, напротив, создается объект типа TLinkGridToDataSourceBindSourceDB.

    image

    В инспекторе объектов мы можем отредактировать список полей. Для этого вызовем свойство Columns и в редакторе полей нажмем кнопку Add All Fields. К слову, этот редактор очень напоминает редактор полей в TDBGrid. Для каждого из полей можно отредактировать свойства, в частности ширину поля и текст заголовка. Кроме этого, можно создать новое поле, и задать выражение (свойство CustomFormat) для отображения в столбце таблицы. Так для того, что бы отобразить комбинацию Id и аббревиатуры, мы можем задать такое выражение:

    DataSet.FieldByName('Id').AsString +" - "+DataSet.FieldByName('Abbr').AsString
    


    Как следует из вышесказанного, механизм LiveBinding предоставляет достаточно широкие возможности для отображения данных. LiveBinding дизайнер, в свою очередь, позволяет визуализировать и упростить процесс связывания визуальных компонентов с источником данных.
    В заключение рассмотрим еще один прием работы с LiveBinding. В дизайнере сделайте активным поле Abbr элемента DM. FDTUnits и в контекстном меню выберите пункт Link to new control… (Связать с новым элементом управления…). В появившемся списке выберите значение TEdit.



    Нажмите кнопку «Ок» и на форме будет размещен новый элемент управления TEdit и «приклеенная» к нему метка TLabel. Вам останется только поместить данный объект в нужную позицию и задать нужное значение свойства Text метки.



    Вызов форм редактирования списков из главной формы организуем с помощью меню. На главной форме поместим компонент TMainMenu. Двойным щелчком вызовем редактор меню. И создадим несколько пунктов, так как это показано на рисунке.



    Для пункта меню “Единицы измерения” зададим следующий обработчик события OnClick:

    procedure TfMain.aSprUnitExecute(Sender: TObject);
    begin
    fSprUnits.ShowModal;
    end;
    


    Естественно, модуль с формой-списком необходимо подключить к главной форме.

    implementation
    
    {$R *.fmx}
    
    uses uAddRecipe, uSprUnit;
    


    Форму-список продуктов вы можете сделать по аналогии.

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

    До следующей пятницы!
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 4

      +6
      Не принимайте на личный счет, но программирование на Delphi для Android это онанизм какой-то.
      И пусть меня покарают если, кто-то думает иначе.
        0
        Собственно, как и для iOS. Hello World приложение весит от 30 мбайт. Замечательно, что тут скажешь.
        Отличие возможно только в том, что онанизм еще доставляет удовольствие.
          0
          Я такого же мнения, но знаю многих людей которые в восторге от этой новости, и программирование на Delphi под мобильные платформы доставит им не мало удовольствия и денег.
            +2
            Если есть большой десктопный проект со сложной логикой, то лучше нарисовать десяток формочек в Delphi и прилинковать к нему уже готовую кодовую базу чем переписывать всё на Java, а потом на Objective C. И что такое сейчас 30 мегабайт? Я понимаю что если у вас стоит сотня игрух, то это много. Но для корпоративного сектора нормальна ситуация когда гаджет покупается для использования 2-3 программ. В таких условиях даже на самых бюджетных моделях нет проблем с ресурсами.

            И, да, для кого-то Delphi на мобильных устройствах это онанизм, а для кого-то такой-же онанизм — Java на десктопах. Всё зависит от того что первично: десктопы или портативные устройства. Еслю у вас весь бизнеспроцесс завязан на мобильники и планшеты, а несктопы используются постольку-поскольку, то да, лучше всё изначально писать на Java. Если же наоборот — Delphi какраз рулит.

          Only users with full accounts can post comments. Log in, please.