Использование и реализация UriLinkAPI и событий UriOpening
Использование и реализация API для обработки ссылок¶
Пример реализации пользовательского обработчика ссылок IUriLinkHandler
для desktop-клиента:
namespace Tessa.Extensions.Client
{
// Класс TestUriLinkHandler наследуем от StandardUriLinkHandler, чтобы иметь доступ к стандартной функциональности обработки ссылок.
public class TestUriLinkHandler : StandardUriLinkHandler
{
public override async ValueTask OpenAsync(Uri uri, UriLinkHandlerEventType eventType, CancellationToken cancellationToken = default)
{
switch (eventType)
{
case UriLinkHandlerEventType.HtmlPreview:
// Действия в случае возникновения события из предпросмотра html.
break;
case UriLinkHandlerEventType.HyperLinkLabel:
// Действия в случае возникновения события из контрола "Метка".
break;
// В остальных случаях ссылка обработается стандартным обработчиком.
case UriLinkHandlerEventType.FormattedText:
case UriLinkHandlerEventType.Default:
default:
await base.OpenAsync(uri, eventType, cancellationToken);
break;
}
}
}
}
Регистрация пользовательского обработчика в DI:
namespace Tessa.Extensions.Client
{
[Registrator]
public sealed class TestUriLinkHandlerRegistrator : RegistratorBase
{
public override void FinalizeRegistration()
{
this.UnityContainer
.RegisterType<IUriLinkHandler, TestUriLinkHandler>(new ContainerControlledLifetimeManager());
}
}
}
Имплементация API для обработки ссылок в других местах, не предусмотренных стандартным решением¶
Note
Примеры сильно упрощены, и служат для того, чтобы показать простоту имплементации и необходимые шаги для этого. Вероятнее всего в реальности фабрику зависимостей будет получать объект где-то по цепочке выше, затем создавать зависимости и саму вью-модель, передавая в нее эти зависимости.
Пример вью-модели с имплементацией UriLinkAPI:
public class CustomViewModel : ViewModel<EmptyModel>
{
private readonly IUriLinkDependenciesFactory uriLinkDependenciesFactory;
// Необходимо получить фабрику зависимостей из DI:
public CustomViewModel(IUriLinkDependenciesFactory uriLinkDependenciesFactory)
{
this.uriLinkDependenciesFactory = uriLinkDependenciesFactory;
}
// Some code...
// Метод обработки ссылки.
public async ValueTask OnUriOpeningAsync(Uri uri, ICardModel cardModel, CancellationToken cancellationToken = default)
{
// Получаем зависимости для обработки ссылок.
// Если UIContextExecutor не задан, действие будет выполняться в неизвестном контексте (т.е. будет использован UIHelper.UnknownContextExecutorAsync).
var uriLinkDependencies = this.uriLinkDependenciesFactory.Create(cardModel.UIContextExecutorAsync);
// Запускаем действие через UiContextExecutorAsync из зависимостей, он выполняет заданный метод в контексте IUIContext,
// который устанавливается как текущий контекст и передаётся как параметр в заданный метод.
await uriLinkDependencies.UiContextExecutorAsync.Invoke
(async (context, ct) =>
{
await uriLinkDependencies.UriLinkHandler.OpenAsync(uri, UriLinkHandlerEventType.Default, ct);
}, cancellationToken);
}
// Some code...
}
Определение пользовательских обработчиков событий UriOpening для контролов “Текст с форматированием” и форумов (обсуждений)¶
Пример desktop-расширения, которое добавляет обработчик события UriOpening в карточках типа “Автомобиль” для всех контролов “Текст с форматированием”.
public sealed class CarUriOpeningUIExtension : CardUIExtension
{
public override Task Initialized(ICardUIExtensionContext context)
{
if (context.Card.TypeID != DefaultCardTypes.CarTypeID) // CarTypeID - id типа карточки "Автомобиль"
{
return Task.CompletedTask;
}
this.AddHandlers(context);
return Task.CompletedTask;
}
private void AddHandlers(ICardUIExtensionContext context)
{
// Все контролы "Текст с форматированием".
var controls = context.Model.Forms
.SelectMany(x => x.Blocks)
.SelectMany(x => x.Controls)
.Where(x => x is CustomRichTextBoxViewModel).Cast<CustomRichTextBoxViewModel>()
.ToList();
foreach (var control in controls)
{
// Добавление обработчика события.
control.RichTextBox.UriOpening += this.LinkHandler;
}
return;
}
private void LinkHandler(object sender, UriLinkEventArgs e)
{
if (!e.Cancel) // Если требуется проверить не обработана ли данная ссылка уже в другом событии.
{
// Do something...
e.Cancel = true; // True, если требуется отменить вызов глобального обработчика после обработчика события UriOpening.
e.Handled = true; // Это свойство можно использовать, чтобы обозначить, что событие было обработано.
}
}
}