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

Расширение, обновляющее узел дерева по таймеру

Расширение, обновляющее узел дерева по таймеру

Напишем расширение, которое можно будет добавить к узлу дерева “Мои задания”. Для этого после компиляции примера в TessaAdmin выделяем узел “Мои задания” и добавляем наше расширение RefreshMyTasksExtension.

Расширение позволяет:

  • Обновить текстовое представление узла, чтобы рядом с узлом выводилось количество новых заданий, например: “Мои задания - 5”.

  • Обновить раскрытые сабсеты в дереве, если сейчас не выбран один из узлов в сабсете (иначе узел “схлопнется” и выделение перебросится на один из родительских узлов).

  • Обновить таблицу с заданиями, если сейчас выбран узел “Мои задания” или один из его сабсетов.

Расширение запускает таймер, который обновляет задания только в том случае, если вкладка с рабочим местом “Пользователь” сейчас активна. Если пользователю недоступен узел дерева, с которым связано расширение, то каких-либо действий выполняться не будет.

using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Threading; using NLog; using Tessa.UI.Views; using Tessa.UI.Views.Extensions; using Tessa.UI.Views.Workplaces.Tree; using Unity; using Unity.Lifetime;

namespace Tessa.Extensions.Client.Views { public sealed class RefreshMyTasksExtension : ITreeItemExtension { private DispatcherTimer timer;

private Task asyncTask;

private static readonly Logger logger = LogManager.GetCurrentClassLogger();

private int GetTaskCountAsync(int previousCount) { // TODO здесь получаем количество заданий из базы, используем любые зависимости, полученные через конструктор

// например, через ICardRepository выполняем кастомный реквест, // который в response.Info получает количество заданий: // this.cardRepository.Request(new CardRequest {RequestType = ...})

Thread.Sleep(500); return previousCount < 10 ? previousCount + 1 : 0; }

private static void NotifyTaskArrived( IWorkplaceViewModel workplace, int taskCount, ITreeItem node, string nodeText) { // TODO здесь можно обновить UI, например, мы меняем текст узла, добавляя к нему количество заданий node.Text = taskCount > 0 ? nodeText + " - " + taskCount : nodeText;

// далее можно обновить раскрытые сабсеты, а также содержимое узла bool childSelected = false;

ITreeItem currentItem = workplace.CurrentItem; if (currentItem != node) { while (currentItem != null) { if (currentItem == node) { childSelected = true; break; }

currentItem = currentItem.Parent; } }

// если не выбран дочерний узел, то рефрешим все узлы if (!childSelected) { node.RefreshNode(); }

// если выбран узел или его дочерний узел, то рефрешим таблицу и перекидываем номер страницы на первый if (childSelected || node.IsSelected) { IViewContext viewContext = workplace.Context.ViewContext; if (viewContext != null) { IViewContext rootContext = viewContext.GetRoot(); IWorkplaceViewComponent viewComponent = rootContext.TryGetViewContainer();

if (viewComponent == null || viewComponent.CurrentPage == 1) { rootContext.RefreshView(); } else { viewComponent.CurrentPage = 1; } } } }

public void Initialized(ITreeItem model) { string initialText = model.Text; // локализованный текст узла "Мои задания" int prevTaskCount = 0;

IWorkplaceViewModel workplace = model.Workplace;

// таймер тикает каждую секунду, за каждый тик отправляется запрос на сервер this.timer = new DispatcherTimer(DispatcherPriority.ApplicationIdle) { Interval = TimeSpan.FromSeconds(10), };

timer.Tick += (s, e) => { UIHelper.InvokeAsync( () => this.GetTaskCountAsync(prevTaskCount), taskCount => { try { if (taskCount != prevTaskCount) { NotifyTaskArrived(workplace, taskCount, model, initialText); prevTaskCount = taskCount; } } catch (Exception ex) { logger.Log(LogLevel.Error, ex); // не показываем окно с исключением, чтобы не мешать пользователю } }); };

workplace.PropertyChanged += (s, e) => { if (e.PropertyName == "IsActive") { if (model.Workplace.IsActive) { // вкладка с рабочим местом активирована timer.Start(); } else { // вкладка с рабочим местом деактивирована timer.Stop(); } } };

if (model.Workplace.IsActive) { // вкладка с рабочим местом активна на момент запуска приложения timer.Start(); } }

public void Initialize(ITreeItem model) { }

public void Clone(ITreeItem source, ITreeItem cloned, ICloneableContext context) { } }

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

public override void FinalizeRegistration() { if (this.UnityContainer.IsRegistered<IWorkplaceExtensionRegistry>()) { this.UnityContainer .Resolve<IWorkplaceExtensionRegistry>() .Register(typeof(RefreshMyTasksExtension)) ; } } } }

Back to top