Поделиться через


Введение в MonoTouch.Dialog для Xamarin.iOS

MonoTouch.Dialog, называемый MT. D для краткого представления — это быстрый набор средств разработки пользовательского интерфейса, позволяющий разработчикам создавать экраны приложений и навигацию с помощью информации, а не создавать контроллеры представления, таблицы и т. д. Таким образом, он обеспечивает значительное упрощение разработки пользовательского интерфейса и сокращения кода. Например, рассмотрим следующий снимок экрана:

For example, consider this screenshot

Следующий код использовался для определения всего экрана:

public enum Category
{
    Travel,
    Lodging,
    Books
}
        
public class Expense
{
    [Section("Expense Entry")]

    [Entry("Enter expense name")]
    public string Name;
    [Section("Expense Details")]
  
    [Caption("Description")]
    [Entry]
    public string Details;
        
    [Checkbox]
    public bool IsApproved = true;
    [Caption("Category")]
    public Category ExpenseCategory;
}

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

MT. D упрощает это путем инкапсулирования всего этого кода в универсальный API для создания таблиц. Затем он предоставляет абстракцию поверх этого API, который позволяет декларативным синтаксисом привязки объектов, что делает его еще проще. Таким образом, существует два API, доступных в MT. D:

  • API элементов низкого уровня — API элементов основан на создании иерархического дерева элементов, представляющих экраны и их компоненты. API Элементов дает разработчикам большую гибкость и контроль при создании пользовательских интерфейсов. Кроме того, API Элементов имеет расширенную поддержку декларативного определения через JSON, что позволяет как для невероятно быстрого объявления, так и динамического создания пользовательского интерфейса с сервера.
  • API высокого уровня Рефлексия ion — также известный как API привязки, в котором классы аннотируются с указанием пользовательского интерфейса, а затем MT. D автоматически создает экраны на основе объектов и предоставляет привязку между отображаемыми (и необязательными изменениями) на экране и базовой резервной копией объекта. В приведенном выше примере показано использование API Рефлексия ion. Этот API не предоставляет точное управление, которое выполняет API элементов, но снижает сложность еще больше, автоматически создавая иерархию элементов на основе атрибутов класса.

MT. D поставляется с большим набором встроенных элементов пользовательского интерфейса для создания экрана, но также распознает необходимость настраиваемых элементов и расширенных макетов экрана. Таким образом, расширяемость — это первый класс, который выпекается в API. Разработчики могут расширить существующие элементы или создать новые, а затем легко интегрировать.

Кроме того, MT. D имеет ряд распространенных функций пользовательского интерфейса iOS, таких как поддержка "вытягивания к обновлению", асинхронная загрузка образов и поддержка поиска.

В этой статье вы узнаете, как работать с MT. D, включая:

  • MT. Компоненты D . Это будет сосредоточено на понимании классов, составляющих MT. D, чтобы быстро приступить к скорости.
  • Справочник по элементам — полный список встроенных элементов MT.D.
  • Расширенное использование — это дополнительные функции, такие как вытягивание к обновлению, поиск, загрузка фонового изображения, использование LINQ для построения иерархий элементов и создание пользовательских элементов, ячеек и контроллеров для использования с MT.D.

Настройка MT. D

MT. D распространяется с помощью Xamarin.iOS. Чтобы использовать его, щелкните правой кнопкой мыши узел "Ссылки" проекта Xamarin.iOS в Visual Studio 2017 или Visual Studio для Mac и добавьте ссылку на сборку MonoTouch.Dialog-1. Затем добавьте using MonoTouch.Dialog инструкции в исходный код по мере необходимости.

Общие сведения о кусках MT. D

Даже при использовании API Рефлексия ion MT. D создает иерархию элементов под капотом так же, как если бы она была создана через API элементов напрямую. Кроме того, поддержка JSON, упоминание в предыдущем разделе, также создает элементы. По этой причине важно иметь базовое понимание составляющих частей MT.D.

MT. D создает экраны с помощью следующих четырех частей:

  • DialogViewController
  • RootElement
  • Раздел
  • Element

DialogViewController

Объект DialogViewController или DVC для короткого времени наследует и UITableViewController поэтому представляет экран с таблицей. DvCs можно отправить на контроллер навигации так же, как обычный UITableViewController.

RootElement

RootElement — это контейнер верхнего уровня для элементов, которые отправляются в DVC. Он содержит разделы, которые затем могут содержать элементы. RootElements не отображаются; вместо этого они просто контейнеры для того, что на самом деле получает отрисовку. RootElement назначается DVC, а затем DVC отрисовывает дочерние элементы.

Раздел

Раздел — это группа ячеек в таблице. Как и в обычном разделе таблицы, он может при необходимости иметь верхний и нижний колонтитул, который может быть текстом или даже пользовательскими представлениями, как показано на следующем снимке экрана:

As with a normal table section, it can optionally have a header and footer that can either be text, or even custom views, as in this screenshot

Элемент

Элемент представляет фактическую ячейку в таблице. MT. D поставляется с широким спектром элементов, представляющих различные типы данных или различные входные данные. Например, на следующих снимках экрана показано несколько доступных элементов:

For example, this screenshots illustrate a few of the available elements

Дополнительные сведения о разделах и RootElements

Теперь рассмотрим RootElements и разделы более подробно.

RootElements

Для запуска процесса MonoTouch.Dialog требуется по крайней мере один RootElement.

Если rootElement инициализирован со значением раздела или элемента, то это значение используется для поиска дочернего элемента, который будет предоставлять сводку конфигурации, которая отображается справа от дисплея. Например, на снимок экрана ниже показана таблица слева с ячейкой, содержащей заголовок экрана сведений справа, "Десерт", а также значение выбранной пустыни.

This screenshot shows a table on the left with a cell containing the title of the detail screen on the right, Dessert, along with the value of the selected desertThis screenshot below shows a table on the left with a cell containing the title of the detail screen on the right, Dessert, along with the value of the selected desert

Корневые элементы также можно использовать внутри разделов для активации загрузки новой вложенной страницы конфигурации, как показано выше. При использовании в этом режиме предоставленный подпись используется во время отрисовки внутри раздела, а также используется в качестве заголовка для вложенной страницы. Например:

var root = new RootElement ("Meals") {
    new Section ("Dinner") {
        new RootElement ("Dessert", new RadioGroup ("dessert", 2)) {
            new Section () {
                new RadioElement ("Ice Cream", "dessert"),
                new RadioElement ("Milkshake", "dessert"),
                new RadioElement ("Chocolate Cake", "dessert")
            }
        }
    }
};

В приведенном выше примере, когда пользователь нажимает "Десерт", MonoTouch.Dialog создаст новую страницу и перейдет к ней с корнем "Десерт" и имеет радиогруппу с тремя значениями.

В этом примере радиогруппа выберет "Шоколадный торт" в разделе "Десерт", так как мы передали значение "2" в RadioGroup. Это означает, что выберите 3-й элемент в списке (нулевой индекс).

Вызов метода Add или использование синтаксиса инициализатора C# 4 добавляет разделы. Методы insert предоставляются для вставки разделов с анимацией.

При создании RootElement с экземпляром группы (вместо radioGroup) сводное значение RootElement при отображении в разделе будет совокупным числом всех логических элементов и флажков, имеющих тот же ключ, что и значение Group.Key.

Разделы

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

RootElements, внедренные в раздел, используются для перехода к новому более глубокому уровню.

Разделы могут иметь верхние и нижние колонтитулы как строки, так и как UIViews. Как правило, вы будете использовать только строки, но для создания пользовательских UIs можно использовать любой UIView в качестве верхнего или нижнего колонтитула. Вы можете использовать строку для создания таких строк:

var section = new Section ("Header", "Footer");

Чтобы использовать представления, просто передайте представления конструктору:

var header = new UIImageView (Image.FromFile ("sample.png"));
var section = new Section (header);

Получение уведомлений

Обработка NSAction

MT. D представляет собой NSAction делегат для обработки обратных вызовов. Например, предположим, что вы хотите обработать событие касания для ячейки таблицы, созданной MT.D. При создании элемента с помощью MT. D, просто укажите функцию обратного вызова, как показано ниже:

new Section () {
    new StringElement ("Demo Callback", delegate { Console.WriteLine ("Handled"); })
}

Получение значения элемента

В сочетании со свойством обратный Element.Value вызов может получить значение, заданное в других элементах. Рассмотрим следующий пример кода:

var element = new EntryElement (task.Name, "Enter task description", task.Description);
                
var taskElement = new RootElement (task.Name) {
    new Section () { element },
    new Section () { new DateElement ("Due Date", task.DueDate) },
    new Section ("Demo Retrieving Element Value") {
        new StringElement ("Output Task Description", delegate { Console.WriteLine (element.Value); })
    }
};

Этот код создает пользовательский интерфейс, как показано ниже. Полное пошаговое руководство по этому примеру см. в руководстве по API элементов.

Combined with the Element.Value property, the callback can retrieve the value set in other elements

Когда пользователь нажимает нижнюю ячейку таблицы, код в анонимной функции выполняется, записывая значение из element экземпляра на панель вывода приложения в Visual Studio для Mac.

Встроенные элементы

MT. D поставляется с рядом встроенных элементов ячейки таблицы, известных как Элементы. Эти элементы используются для отображения различных типов в ячейках таблицы, таких как строки, с плавающей запятой, даты и даже изображения, чтобы назвать лишь несколько. Каждый элемент заботится о правильном отображении типа данных. Например, логический элемент отобразит переключатель для переключения его значения. Аналогичным образом, элемент float будет отображать ползунок для изменения значения float.

Существуют еще более сложные элементы для поддержки более богатых типов данных, таких как изображения и html. Например, html-элемент, который откроет UIWebView для загрузки веб-страницы при выборе, отображает подпись в ячейке таблицы.

Работа со значениями элементов

Элементы, используемые для записи входных данных пользователя, предоставляют общедоступное Value свойство, которое содержит текущее значение элемента в любое время. Он автоматически обновляется, так как пользователь использует приложение.

Это поведение для всех элементов, входящих в MonoTouch.Dialog, но не требуется для элементов, созданных пользователем.

Элемент String

Отображается StringElement подпись в левой части ячейки таблицы и строковое значение в правой части ячейки.

A StringElement shows a caption on the left side of a table cell and the string value on the right side of the cell

Чтобы использовать StringElement в качестве кнопки, укажите делегат.

new StringElement ("Click me", () => { 
    new UIAlertView("Tapped", "String Element Tapped", null, "ok", null).Show();
});

To use a StringElement as a button, provide a delegate

Элемент Styled String

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

A StyledStringElement allows strings to be presented using either built-in table cell styles or with custom formatting

Класс StyledStringElement является производным от StringElement, но позволяет разработчикам настраивать несколько свойств, таких как шрифт, цвет текста, цвет фона, цвет ячейки фона, режим разбиения строк, количество строк для отображения и необходимость отображения аксессуара.

Элемент Multiline

Multiline Element

Элемент Entry

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

The EntryElement is used to get user input

Он инициализирован с тремя значениями:

  • Подпись для записи, которая будет отображаться пользователю.
  • Замещающий текст (это серый текст, предоставляющий указание пользователю).
  • Значение текста.

Заполнитель и значение могут иметь значение NULL. Однако требуется подпись.

В любой момент, доступ к свойству Value может получить значение EntryElement.

Кроме того, KeyboardType свойство можно задать во время создания для стиля типа клавиатуры, требуемого для записи данных. Это можно использовать для настройки клавиатуры с помощью значений, указанных UIKeyboardType ниже.

  • Числовое
  • Номер телефона
  • URL
  • Эл. почта

Логический элемент

Boolean Element

Элемент Checkbox

Checkbox Element

Элемент Radio

Требуется RadioElement указывать в элементе RootElement.RadioGroup

mtRoot = new RootElement ("Demos", new RadioGroup("MyGroup", 0));

A RadioElement requires a RadioGroup to be specified in the RootElement

RootElements также используются для координации радиоэлеготов. Члены RadioElement могут охватывать несколько разделов (например, реализовать что-то подобное селектору тонов кольца и отделять тоны пользовательского кольца от системных мелодий). В представлении сводки отображается выбранный в данный момент элемент радио. Для этого создайте RootElement конструктор группы следующим образом:

var root = new RootElement ("Meals", new RadioGroup ("myGroup", 0));

Имя группы RadioGroup используется для отображения выбранного значения на содержащей странице (если она есть) и значения, которое равно нулю в данном случае, является индексом первого выбранного элемента.

Элемент Индикатора событий

Badge Element

Элемент Float

Float Element

Элемент Activity

Activity Element

Элемент Date

Date Element

Если выбрана ячейка, соответствующая DateElement, средство выбора дат отображается, как показано ниже:

When the cell corresponding to the DateElement is selected, a date picker is presented as shown

Time, элемент

Time Element

При выборе ячейки, соответствующей TimeElement, отображается средство выбора времени, как показано ниже:

When the cell corresponding to the TimeElement is selected, a time picker is presented as shown

Элемент DateTime

DateTime Element

Если выбрана ячейка, соответствующая DateTimeElement, средство выбора даты и времени отображается, как показано ниже:

When the cell corresponding to the DateTimeElement is selected, a datetime picker is presented as shown

ЭЛЕМЕНТ HTML

HTML Element

Отображает HTMLElement значение его Caption свойства в ячейке таблицы. Выбранный Whe, Url назначенный элементу UIWebView , загружается в элемент управления, как показано ниже:

Whe selected, the Url assigned to the element is loaded in a UIWebView control as shown below

Элемент сообщения

Message Element

Загрузить дополнительный элемент

Используйте этот элемент, чтобы разрешить пользователям загружать больше элементов в списке. Можно настроить обычные и загружаемые подпись, а также цвет шрифта и текста. Индикатор UIActivity начинает анимироваться, а загрузка подпись отображается при нажатии пользователя ячейки, а затем NSAction передается в конструктор. После завершения UIActivity кода NSAction индикатор перестает анимировать и снова отображается обычный подпись.

Элемент UIView

Кроме того, любое пользовательское UIView можно отобразить с помощью .UIViewElement

Элемент ,нарисованный владельцем

Этот элемент должен быть подклассом, так как это абстрактный класс. Необходимо переопределить Height(RectangleF bounds) метод, в котором следует вернуть высоту элемента, а также Draw(RectangleF bounds, CGContext context, UIView view) сделать все настраиваемые рисунки в заданных границах с помощью параметров контекста и представления. Этот элемент делает тяжелый подъем подкласса UIViewи помещает его в ячейку, чтобы вернуться, оставляя только необходимо реализовать два простых переопределения. В примере приложения в DemoOwnerDrawnElement.cs файле можно увидеть более эффективную реализацию.

Ниже приведен очень простой пример реализации класса:

public class SampleOwnerDrawnElement : OwnerDrawnElement
{
    public SampleOwnerDrawnElement (string text) : base(UITableViewCellStyle.Default, "sampleOwnerDrawnElement")
    {
        this.Text = text;
    }

    public string Text { get; set; }

    public override void Draw (RectangleF bounds, CGContext context, UIView view)
    {
        UIColor.White.SetFill();
        context.FillRect(bounds);

        UIColor.Black.SetColor();   
        view.DrawString(this.Text, new RectangleF(10, 15, bounds.Width - 20, bounds.Height - 30), UIFont.BoldSystemFontOfSize(14.0f), UILineBreakMode.TailTruncation);
    }

    public override float Height (RectangleF bounds)
    {
        return 44.0f;
    }
}

Элемент JSON

Это JsonElement подкласс RootElement , который расширяет RootElement возможность загрузки содержимого вложенного дочернего элемента из локального или удаленного URL-адреса.

Это JsonElement объект RootElement , который можно создать в двух формах. Одна версия создает содержимое RootElement по запросу. Они создаются с помощью JsonElement конструкторов, которые принимают дополнительный аргумент в конце, URL-адрес для загрузки содержимого из:

var je = new JsonElement ("Dynamic Data", "https://tirania.org/tmp/demo.json");

Другая форма создает данные из локального файла или существующего System.Json.JsonObject , который вы уже анализируете:

var je = JsonElement.FromFile ("json.sample");
using (var reader = File.OpenRead ("json.sample"))
    return JsonElement.FromJson (JsonObject.Load (reader) as JsonObject, arg);

Дополнительные сведения об использовании JSON с MT. D, см. руководство по пошаговому руководству по элементу JSON.

Другие возможности

Поддержка обновления по запросу

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

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

Подключение уведомления простое; Просто подключитесь к событию RefreshRequested в DialogViewControllerследующем:

dvc.RefreshRequested += OnUserRequestedRefresh;

Затем в методе OnUserRequestedRefreshвы будете очереди загрузки некоторых данных, запрашивать некоторые данные из сети или спинировать поток для вычисления данных. После загрузки данных необходимо уведомить DialogViewController о том, что новые данные включено, а также восстановить представление до его состояния по умолчанию, выполнив вызов:ReloadComplete

dvc.ReloadComplete ();

Поддержка поиска

Чтобы поддержать поиск, задайте свойство в вашей учетной EnableSearch записи DialogViewController. Вы также можете задать SearchPlaceholder свойство, которое будет использоваться в качестве подложки в строке поиска.

Поиск изменит содержимое представления в качестве типов пользователей. Он выполняет поиск видимых полей и показывает их пользователю. Предоставляет DialogViewController три метода для программного инициирования, завершения или активации новой операции фильтра в результатах. Ниже перечислены следующие методы.

  • StartSearch
  • FinishSearch
  • PerformFilter

Система расширяема, поэтому вы можете изменить это поведение, если вы хотите.

Загрузка фонового изображения

MonoTouch.Dialog включает загрузчик изображений приложения TweetStation . Этот загрузчик изображений можно использовать для загрузки изображений в фоновом режиме, поддерживает кэширование и может уведомлять код о загрузке образа.

Он также ограничивает количество исходящих сетевых подключений.

Загрузчик изображений реализуется в ImageLoader классе, все, что необходимо сделать, — вызвать DefaultRequestImage метод, необходимо указать универсальный код ресурса (URI) для изображения, который требуется загрузить, а также экземпляр IImageUpdated интерфейса, который будет вызываться при загрузке образа.

Например, следующий код загружает изображение из URL-адреса в BadgeElement:

string uriString = "http://some-server.com/some image url";

var rootElement = new RootElement("Image Loader") {
    new Section() {
        new BadgeElement( ImageLoader.DefaultRequestImage( new Uri(uriString), this), "Xamarin")
    }
};

Класс ImageLoader предоставляет метод очистки, который можно вызвать, когда требуется освободить все образы, которые в настоящее время кэшируются в памяти. Текущий код содержит кэш для 50 образов. Если вы хотите использовать другой размер кэша (например, если вы ожидаете, что изображения будут слишком большими, что 50 образов было бы слишком много), можно просто создать экземпляры ImageLoader и передать количество изображений, которые вы хотите сохранить в кэше.

Использование LINQ для создания иерархии элементов

Используя умный синтаксис инициализации LINQ и C#, LINQ можно использовать для создания иерархии элементов. Например, следующий код создает экран из некоторых строковых массивов и обрабатывает выделение ячеек с помощью анонимной функции, передаваемой в каждую StringElement:

var rootElement = new RootElement ("LINQ root element") {
    from x in new string [] { "one", "two", "three" }
    select new Section (x) {
        from y in "Hello:World".Split (':')
        select (Element) new StringElement (y, delegate { Debug.WriteLine("cell tapped"); })
    }
};

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

Расширение MT. D

Создание пользовательских элементов

Вы можете создать собственный элемент, наследуя от существующего элемента или из корневого элемента класса.

Чтобы создать собственный элемент, необходимо переопределить следующие методы:

// To release any heavy resources that you might have
void Dispose (bool disposing);

// To retrieve the UITableViewCell for your element
// you would need to prepare the cell to be reused, in the
// same way that UITableView expects reusable cells to work
UITableViewCell GetCell (UITableView tv);

// To retrieve a "summary" that can be used with
// a root element to render a summary one level up.  
string Summary ();

// To detect when the user has tapped on the cell
void Selected (DialogViewController dvc, UITableView tableView, NSIndexPath path);

// If you support search, to probe if the cell matches the user input
bool Matches (string text);

Если элемент может иметь размер переменной, необходимо реализовать IElementSizing интерфейс, содержащий один метод:

// Returns the height for the cell at indexPath.Section, indexPath.Row
float GetHeight (UITableView tableView, NSIndexPath indexPath);

Если вы планируете реализовать GetCell метод путем вызова base.GetCell(tv) и настройки возвращаемой ячейки, необходимо также переопределить CellKey свойство, чтобы вернуть ключ, который будет уникальным для элемента, как показано ниже.

static NSString MyKey = new NSString ("MyKey");
protected override NSString CellKey {
    get {
        return MyKey;
    }
}

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

DialogViewControllers (DVCS)

И Рефлексия, и API элементов используют одинаковыеDialogViewController. Иногда вы хотите настроить внешний вид представления или вы можете использовать некоторые функции UITableViewController , которые выходят за рамки базового создания пользовательских интерфейсов.

Это DialogViewController просто подкласс и UITableViewController вы можете настроить его таким же образом, как и настроить UITableViewController.

Например, если вы хотите изменить стиль GroupedPlainсписка или задать это значение, изменив свойство при создании контроллера, например:

var myController = new DialogViewController (root, true) {
    Style = UITableViewStyle.Grouped;
}

Для более сложных настроек, таких как настройка фона DialogViewController, вы будете подклассить его и переопределить правильные методы, как показано в следующем примере:

class SpiffyDialogViewController : DialogViewController {
    UIImage image;

    public SpiffyDialogViewController (RootElement root, bool pushing, UIImage image) 
        : base (root, pushing) 
    {
        this.image = image;
    }

    public override LoadView ()
    {
        base.LoadView ();
        var color = UIColor.FromPatternImage(image);
        TableView.BackgroundColor = UIColor.Clear;
        ParentViewController.View.BackgroundColor = color;
    }
}

Другая точка настройки — это следующие виртуальные методы в DialogViewController:

public override Source CreateSizingSource (bool unevenRows)

Этот метод должен возвращать подкласс DialogViewController.Source для случаев, когда ячейки равномерно размером или подклассом DialogViewController.SizingSource , если ячейки неровны.

Это переопределение можно использовать для записи любого из UITableViewSource методов. Например, TwitterStation использует это для отслеживания, когда пользователь прокрутился в верхнюю часть и обновляет соответственно количество непрочитанных твитов.

Проверка

Элементы не предоставляют проверку как модели, которые хорошо подходят для веб-страниц и классических приложений, не сопоставляются непосредственно с моделью взаимодействия i Телефон.

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

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

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

Итоги

В этой статье описано много сведений о MonoTouch.Dialog. Он обсудил основы того, как MT. D работает и охватывает различные компоненты, составляющие MT.D. Он также показал широкий массив элементов и настроек таблиц, поддерживаемых MT. D и обсудил, как MT. D можно расширить с помощью пользовательских элементов. Кроме того, он объяснил поддержку JSON в MT. D, который позволяет динамически создавать элементы из JSON.