gpt4 book ai didi

xaml - 自动检测 TextBlock 中的 URL、电话号码、电子邮件

转载 作者:行者123 更新时间:2023-12-04 00:38:16 24 4
gpt4 key购买 nike

我想在 UWP 中自动突出显示 URL、电子邮件和电话号码。这在 Android 中是可能的,但似乎此功能已被 Microsoft 遗忘。在我的用例中,我从网络服务获取文本,所以我不知道网络平台上用户文本输入的文本格式。

最佳答案

该平台(目前)不支持此功能。当我必须做同样的事情时,我以自己的解决方案结束:

  • 创建一个附加属性接收要格式化的文本
  • 使用一些正则表达式从中提取 URL、电话号码、电子邮件地址
  • 生成一个内联集合,我将其注入(inject)到附加的 TextBlock 控件中

使用的正则表达式涵盖了很多情况,但仍然可能缺少一些边缘情况。

它是这样使用的:

<TextBlock  uwpext:TextBlock.InteractiveText="Here is a link www.bing.com to send to a@a.com or 0000000000" />

附加属性代码:

    // -------------------------------------------------------------------------------------------
/// <summary>
/// The regex to detect the URL from the text content
/// It comes from https://gist.github.com/gruber/249502 (http://daringfireball.net/2010/07/improved_regex_for_matching_urls)
/// </summary>
private static readonly Regex UrlRegex = new Regex(@"(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'"".,<>?«»“”‘’]))", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(500));

// -------------------------------------------------------------------------------------------
/// <summary>
/// The regex to detect the email addresses
/// It comes from https://msdn.microsoft.com/en-us/library/01escwtf.aspx
/// </summary>
private static readonly Regex EmailRegex = new Regex(@"(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(500));

// -------------------------------------------------------------------------------------------
/// <summary>
/// The regex to detect the phone numbers from the raw message
/// </summary>
private static readonly Regex PhoneRegex = new Regex(@"\+?[\d\-\(\)\. ]{5,}", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));

// -------------------------------------------------------------------------------------------
/// <summary>
/// The default prefix to use to convert a relative URI to an absolute URI
/// The Windows RunTime is only working with absolute URI
/// </summary>
private const string RelativeUriDefaultPrefix = "http://";


// -------------------------------------------------------------------------------------------
/// <summary>
/// The dependency property to generate an interactive text in a text block.
/// When setting this property, we will parse the value and transform the hyperlink or the email address to interactive fields that the user can interact width.
/// The raw text will be parsed and convert to a collection of inlines.
/// </summary>
public static readonly DependencyProperty InteractiveTextProperty = DependencyProperty.RegisterAttached("InteractiveText", typeof(string), typeof(TextBlock), new PropertyMetadata(null, OnInteractiveTextChanged));

// -------------------------------------------------------------------------------------------
/// <summary>
/// The event callback for the interactive text changed event
/// We will parse the raw text and generate the inlines that will wrap the interactive items (URL...)
/// </summary>
/// <param name="d">the object which has raised the event</param>
/// <param name="e">the change information</param>
private static void OnInteractiveTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBlock = d as Windows.UI.Xaml.Controls.TextBlock;
if(textBlock == null) return;

// we remove all the inlines
textBlock.Inlines.Clear();

// if we have no data, we do not need to go further
var rawText = e.NewValue as string;
if(string.IsNullOrEmpty(rawText)) return;


var lastPosition = 0;
var matches = new Match[3];
do
{
matches[0] = UrlRegex.Match(rawText, lastPosition);
matches[1] = EmailRegex.Match(rawText, lastPosition);
matches[2] = PhoneRegex.Match(rawText, lastPosition);

var firstMatch = matches.Where(x => x.Success).OrderBy(x => x.Index).FirstOrDefault();
if(firstMatch == matches[0])
{
// the first match is an URL
CreateRunElement(textBlock, rawText, lastPosition, firstMatch.Index);
lastPosition = CreateUrlElement(textBlock, firstMatch);
}
else if(firstMatch == matches[1])
{
// the first match is an email
CreateRunElement(textBlock, rawText, lastPosition, firstMatch.Index);
lastPosition = CreateContactElement(textBlock, firstMatch, null);
}
else if(firstMatch == matches[2])
{
// the first match is a phonenumber
CreateRunElement(textBlock, rawText, lastPosition, firstMatch.Index);
lastPosition = CreateContactElement(textBlock, null, firstMatch);
}
else
{
// no match, we add the whole text
textBlock.Inlines.Add(new Run { Text = rawText.Substring(lastPosition) });
lastPosition = rawText.Length;
}
}
while(lastPosition < rawText.Length);
}

// -------------------------------------------------------------------------------------------
/// <summary>
/// This method will extract a fragment of the raw text string, create a Run element with the fragment and
/// add it to the textblock inlines collection
/// </summary>
/// <param name="textBlock">the textblock where to add the run element</param>
/// <param name="rawText">the raw text where the fragment will be extracted</param>
/// <param name="startPosition">the start position to extract the fragment</param>
/// <param name="endPosition">the end position to extract the fragment</param>
private static void CreateRunElement(Windows.UI.Xaml.Controls.TextBlock textBlock, string rawText, int startPosition, int endPosition)
{
var fragment = rawText.Substring(startPosition, endPosition - startPosition);
textBlock.Inlines.Add(new Run { Text = fragment });
}

// -------------------------------------------------------------------------------------------
/// <summary>
/// Create an URL element with the provided match result from the URL regex
/// It will create the Hyperlink element that will contain the URL and add it to the provided textblock
/// </summary>
/// <param name="textBlock">the textblock where to add the hyperlink</param>
/// <param name="urlMatch">the match for the URL to use to create the hyperlink element</param>
/// <returns>the newest position on the source string for the parsing</returns>
private static int CreateUrlElement(Windows.UI.Xaml.Controls.TextBlock textBlock, Match urlMatch)
{
Uri targetUri;
if(Uri.TryCreate(urlMatch.Value, UriKind.RelativeOrAbsolute, out targetUri))
{
var link = new Hyperlink();
link.Inlines.Add(new Run { Text= urlMatch.Value });

if(targetUri.IsAbsoluteUri)
link.NavigateUri = targetUri;
else
link.NavigateUri = new Uri(RelativeUriDefaultPrefix + targetUri.OriginalString);


textBlock.Inlines.Add(link);
}
else
{
textBlock.Inlines.Add(new Run { Text= urlMatch.Value });
}

return urlMatch.Index + urlMatch.Length;
}

// -------------------------------------------------------------------------------------------
/// <summary>
/// Create a hyperlink element with the provided match result from the regex that will open the contact application
/// with the provided contact information (it should be a phone number or an email address
/// This is used only if the email address / phone number is not prefixed with the mailto: / tel: scheme
/// It will create the Hyperlink element that will contain the email/phone number hyperlink and add it to the provided textblock.
/// Clicking on the link will open the contact application
/// </summary>
/// <param name="textBlock">the textblock where to add the hyperlink</param>
/// <param name="emailMatch">the match for the email to use to create the hyperlink element. Set to null if not available but at least one of emailMatch and phoneMatch must be not null.</param>
/// <param name="phoneMatch">the match for the phone number to create the hyperlink element. Set to null if not available but at least one of emailMatch and phoneMatch must be not null.</param>
/// <returns>the newest position on the source string for the parsing</returns>
private static int CreateContactElement(Windows.UI.Xaml.Controls.TextBlock textBlock, Match emailMatch, Match phoneMatch)
{
var currentMatch = emailMatch ?? phoneMatch;

var link = new Hyperlink();
link.Inlines.Add(new Run { Text= currentMatch.Value });
link.Click += (s, a) =>
{
var contact = new Contact();
if(emailMatch != null) contact.Emails.Add(new ContactEmail { Address = emailMatch.Value });
if(phoneMatch != null) contact.Phones.Add(new ContactPhone { Number = phoneMatch.Value.StripNonDigitsCharacters() });

ContactManager.ShowFullContactCard(contact, new FullContactCardOptions());
};

textBlock.Inlines.Add(link);
return currentMatch.Index + currentMatch.Length;
}

// -------------------------------------------------------------------------------------------
/// <summary>
/// Return the InteractiveText value on the provided object
/// </summary>
/// <param name="obj">the object to query</param>
/// <returns>the InteractiveText value</returns>
public static string GetInteractiveText(DependencyObject obj)
{
return (string) obj.GetValue(InteractiveTextProperty);
}

// -------------------------------------------------------------------------------------------
/// <summary>
/// SEt the InteractiveText value on the provided object
/// </summary>
/// <param name="obj">the object to query</param>
/// <param name="value">the value to set</param>
public static void SetInteractiveText(DependencyObject obj, string value)
{
obj.SetValue(InteractiveTextProperty, value);
}

关于xaml - 自动检测 TextBlock 中的 URL、电话号码、电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38208741/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com