При разработке кроссплатформенного приложения возникает вопрос об унификации функционала между разными платформами.
Когда мы разработали Эдусти , мы столкнулись с неожиданной для нас проблемой - отсутствием встроенной функции автоподсветки ссылок в тексте на платформах Windows/Windows Phone, которая присутствует на платформах Android и iOS. Более того, мы даже не нашли сторонних библиотек, реализующих этот функционал.
Нам пришлось реализовать этот функционал самостоятельно.
О том, что произошло, и пойдет речь в этой статье.
На странице, где вы хотите отображать текст со ссылками, есть элемент управления RichTextBlock. Этот элемент управления не поддерживает привязку данных MVVM, поэтому нам пришлось заполнить его по старинке.
Существует три способа заполнения RichTextBlock: 1. Статическая разметка XAML непосредственно в коде страницы.<RichTextBlock Margin="20" x:Name="RTB" FontSize="20"/>
2. Программное наполнение коллекции BlockCollection.Блоки .
Обычно он заполняется объектами типа «Абзац», которые инициализируются объектами, наследующими класс Inline (например, «Выполнить», «Гиперссылка» и т. д.).
3. То же, что и во втором случае, заполнение коллекции Blocks, однако объект Paragraph формируется с использованием статического класса.
XamlReader из разметки XAML (сгенерированной в строковой форме).
В данном случае третий способ будет самым оптимальным, так как позволяет максимально гибко создавать разметку.
Чтобы разобрать строку xaml на объекты, необходимо вызвать метод XamlReader.Load(xamlString).
Этот метод возвращает объект, который можно привести (в нашем случае) к типу «Абзац» и добавить в RichTextBlock.Blocks. RTB.Blocks.Add((Paragraph)XamlReader.Load(xamlString));
Создание строки XAML
Итак, у нас есть строка ввода, содержащая некоторый текст со ссылками или без них, а на выходе должна быть строка с допустимой разметкой xaml для RichTextBlock (тег абзаца), где все ссылки будут в тегах Hyperlink, а обычный текст в тегах Run. .Для этого весь текст разбивается на массив слов пробелами, затем строка вывода начинает формироваться таким образом, чтобы для любой строки ввода всегда были закрыты все теги.
1. В самое начало текста добавляется незакрытый тег Run. 2. Запускается цикл слов, где каждое слово будет проверяться с помощью регулярного выражения, является ли оно ссылкой или нет. Если да, то тег «Выполнить» закрывается и вставляется тег «Гиперссылка» с соответствующей ссылкой, после чего тег «Выполнить» открывается снова.
Если текущее слово не является ссылкой, то мы просто записываем это слово в результат и переходим к следующему слову.
3. Когда все слова разобраны, нужно закрыть тег «Выполнить».
С обработкой ссылок не все так просто, как может показаться на первый взгляд. Для начала определим, какие бывают ссылки: с протоколом или без, с доменом, с IP-адресом, с портом или без, с параметрами или без.
В исходном тексте ссылки могут быть или не быть закодированы в URL. В последнем случае они могут содержать символы, делающие разметку xaml недействительной, поэтому ссылку необходимо обрабатывать методом Uri.EscapeUriString() , который URL-кодирует только параметры ссылки, но не протокол, домен или порт. Однако это еще не все.
Кодировка URL-адреса не заменяет символ «&», однако этот символ также делает разметку xaml недействительной, поэтому его следует заменить HTML-кодом «&».
Также особенностью платформ Windows является то, что для открытия ссылки в другом приложении ОС смотрит, какое приложение установлено по умолчанию для протокола, указанного в этой ссылке (например, http://), поэтому если протокол не указано, открыть такую ссылку ОС не может (фактически даже выдаст исключение UriFormatException).
Итак, к любой ссылке, где не указан протокол, необходимо добавить протокол по умолчанию http://.
Исходный текст иногда может содержать различные символы, нарушающие разметку xaml, поэтому перед размещением его в теге Run его необходимо закодировать в HTML с помощью метода WebUtility.HtmlEncode .
После всего этого формируется новая строка, состоящая из тега «Абзац» с соответствующими параметрами и содержащая ранее сформированный набор тегов.
Разметка Xaml готова.
var words = source.Split(' ');
var sbInsideTags = new StringBuilder();
sbInsideTags.Append(@"<Run Text=""");
foreach (var word in words)
{
if (Regex.IsMatch(word, @"^((https?:\/\/)?(ftps?:\/\/)?[a-z0-9]+([\-\.
]{1}[a-z0-9]+)*\.
[a-z]{2,6}(:[0-9]{1,5})?(\/\S*)?)"))
{
var link = word;
link = link.Replace("&", "&");
link = Uri.EscapeUriString(link);
sbInsideTags.Append(@"""/> <Hyperlink NavigateUri=""");
sbInsideTags.Append(link.Contains("://") ? link : "http://" + link);
sbInsideTags.Append(@""">");
sbInsideTags.Append(link);
sbInsideTags.Append(@"</Hyperlink> <Run Text=""");
}
else
{
sbInsideTags.Append(WebUtility.HtmlEncode(word));
sbInsideTags.Append(' ');
}
}
var sbXaml = new StringBuilder();
sbXaml.Append(@"<Paragraph xmlns="" http://schemas.microsoft.com/winfx/2006/xaml/presentation "" TextAlignment=""Left"" FontSize=""20"" FontWeight=""Normal"" FontStyle=""Normal"" FontStretch=""Normal"" >");
sbXaml.Append(sbInsideTags);
sbXaml.Append(@" ""/></Paragraph>");
return sbXaml.ToString();
Теги: #tom том #XAML #Windows 8.1 #windows phone 8.1 #синтаксический анализ #регулярные выражения #ссылки #Разработка мобильных приложений #Разработка для Windows Phone #Разработка для Windows
-
Игра «Бизнес Акулы».
19 Oct, 24