Перейти к содержанию

Работа с файлами посредством контрола "Представление"

Работа с файлами посредством контрола “Представление”

С помощью расширений можно модифицировать контрол Представление аналогично расширению типа карточки “Список файлов в представлении”.

Проведем декомпозицию данной задачи на подзадачи:

  • Создание представления на клиенте:

    Рассмотрим процесс инициализации контрола представления. Инициализация происходит после выполнения расширений ICardUIExtension.Initializing и до выполнения расширения ICardUIExtension.Initialized по средствам стратегии, реализующей интерфейс IViewCardControlInitializationStrategy. Получение данных строк представления происходит по средством объекта, реализующего интерфейс IDataProvider. В процессе исполнения стандартной стратегии ViewCardControlInitializationStrategy происходит инициализация провайдера данных представления, колонок, кнопок в верхней части контрола. Стандартная стратегия не будет выполнена, если в базе данных будет отсутствовать представление с алиасом, указанным в настройках контрола в TessaAdmin.

Для выполнения данной задачи мы можем получить метаданные из представления, созданного в TessaAdmin (текст sql запроса в этом представлении не важен) и задать кастомный провайдер данных после исполнения стратегии. Сделать это необходимо до выполнения ICardUIExtension.Initialized, так как первое обновление представления может происходить при инициализации открытой вкладки. Для выполнения данной модификации добавим функцию в список функций CardModel.ControlInitializers, выполняемый сразу после инициализации каждого контрола:

public override Task Initializing(ICardUIExtensionContext context) { context.Model.ControlInitializers.Add((control, m, r, ct) => { if (control is CardViewControlViewModel viewControl) { if (viewControl.Name == "YourViewControlAlias") { viewControl.DataProvider = new YourDataProvider(); } } return new ValueTask(); }); return Task.CompletedTask; }

Если требуется создавать метаданные программно, то нам необходимо создать наследника ViewCardControlInitializationStrategy, в которой метаданные будут заданы программно и инициализация представление будет инициализировано на основе программно созданных метаданных. Нам достаточно переопределить методы инициализации метаданых и провайдера данных:

public class YourViewCardControlInitializationStrategy : ViewCardControlInitializationStrategy { public YourViewCardControlInitializationStrategy(IViewService viewService, CreateMenuContextFunc createMenuContextFunc, IViewCardControlContentItemsFactory contentItemsFactory) : base(viewService, createMenuContextFunc, contentItemsFactory) { }

/// <summary> /// Вызывается для инициализации метаданных в модели, заданной в контексте инициализации /// </summary> /// <param name="context">Контекст инициализации</param> public override ValueTask InitializeMatadataAsync(CardViewControlInitializationContext context) { context.ControlViewModel.ViewMetadata = YourCreateMetadataFunc();

return new ValueTask(); }

/// <summary> /// Вызывается для инициализации провадера данных в модели, заданной в контексте инициализации /// </summary> /// <param name="context">Контекст инициализации</param> public override ValueTask InitializeDataProviderAsync(CardViewControlInitializationContext context) { context.ControlViewModel.DataProvider = new YourDataProvider();

return new ValueTask(); } }

Затем нам необходимо исполнить данную стратегию. Мы можем сделать это в CardModel.ControlInitializers, используемом в примере ранее или в ICardUIExtension.Initialized, но, в этом случае если представление расположено на открытой вкладке, то оно не будет инициализировано на вкладке и будет необходимо самостоятельно инициализировать представление на вкладке, вызвав метод CardViewControlViewModel.InitializeOnTabAsync. Кастомный провайдер данных необходимо зарегистрировать в Unity контейнере без указания интерфейса.

[Registrator] public sealed class Registrator : RegistratorBase { public override void RegisterUnity() { this.UnityContainer.RegisterType<ourViewCardControlInitializationStrategy>(new ContainerControlledLifetimeManager()); } }

public sealed class YourUIExtension : CardUIExtension { private readonly IViewCardControlInitializationStrategy initializationStrategy;

// Получаем YourViewCardControlInitializationStrategy из Unity контенера указывая конкретный класс. // Если указать в параметре IViewCardControlInitializationStrategy, то вернется стандартная стратегия инициализации. public YourUIExtension(YourViewCardControlInitializationStrategy initializationStrategy) { this.initializationStrategy = initializationStrategy ?? throw new ArgumentNullException(nameof(initializationStrategy)); }

// Первый способ применении кастомной стратегии инициализации представления. public override Task Initializing(ICardUIExtensionContext context) { context.Model.ControlInitializers.Add(async (control, m, r, ct) => { if (control is CardViewControlViewModel viewControl) { if (viewControl.Name == "YourViewControlAlias") { viewControl.InitializeStrategyAsync(initializationStrategy, true, ct); } } }); return Task.CompletedTask; }

// Второй способ применении кастомной стратегии инициализации представления. public async override Task Initialized(ICardUIExtensionContext context) { if (!context.Model.Controls.TryGet("YourViewControlAlias", out var controlViewModel)) { throw new ArgumentException($"Control ViewModel with Name='{"YourViewControlAlias"}' not found."); } var viewControlViewModel = controlViewModel as CardViewControlViewModel; await viewControlViewModel.InitializeStrategyAsync(initializationStrategy, true, context.CancellationToken); // инициализируем представление на вкладке. await viewControlViewModel.InitializeOnTabAsync(); } }

Tip

Пример стратегии инициализации модели представления доступен в файле FilesViewCardControlInitializationStrategy.cs

  • Модифицировать строки представления:

Если необходимо модифицировать строку один раз при ее создании, то мы можем задать CardViewControlViewModel.CreateRowFunc. Данная функция позволяет с помощью расширений создавать каждую строку и модифицировать ее. Например, добавить тултип или изменить цвет. Для добавления тэгов необходимо добавить функцию CardViewControlViewModel.ModifyRowActions, которая исполняется после инициализации строки ячейками. Тэг это опционально кликабельная иконка с опициональным тултипом, например, в представлении “История заданий” используются тэги с иконкой скрепки для открытия сателлита задания. Рекомендуется использовать IconViewModel.

Tip

Пример использования CardViewControlViewModel.ModifyRowActions доступен в файле WfTaskHistoryViewUIExtension.cs.

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

Tip

Пример наследника ViewControlRowViewModel доступен в файле TableFileRowViewModel.cs.

Back to top