RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1001995
Accepted
Sanvirtus
Sanvirtus
Asked:2020-07-12 15:07:31 +0000 UTC2020-07-12 15:07:31 +0000 UTC 2020-07-12 15:07:31 +0000 UTC

在 TextBlock 中选择文本

  • 772

我有一个自定义 TextBlock 可以检测文本中的链接并使它们可点击。需要添加在 TextBlock 中选择任意文本以将其进一步复制到内存缓冲区的功能。任何想法如何做到这一点?

超链接文本块类:

public class HyperlinkTextBlock : TextBlock
{
    private static readonly Regex HyperlinkRegex = new Regex(@"(https?|ftp):\/\/[^\s/$.?#].[^\s,]*");

    public static readonly DependencyProperty HyperlinkStyleProperty = DependencyProperty.Register("HyperlinkStyle",
        typeof(Style), typeof(HyperlinkTextBlock));

    static HyperlinkTextBlock()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(HyperlinkTextBlock),
            new FrameworkPropertyMetadata(typeof(HyperlinkTextBlock)));
    }

    public HyperlinkTextBlock()
    {
        TargetUpdated += (s, args) =>
            Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(ParseHyperlinks));
    }

    public event EventHandler<HyperlinkPressedEventArgs> HyperlinkPressed;

    public Style HyperlinkStyle
    {
        private get => (Style) GetValue(HyperlinkStyleProperty);
        set => SetValue(HyperlinkStyleProperty, value);
    }

    private void ParseHyperlinks()
    {
        var text = Text;
        var matches = HyperlinkRegex.Matches(text);
        if (matches.Count == 0)
            return;

        Inlines.Clear();
        var lastIndex = 0;
        foreach (Match match in matches)
        {
            Inlines.Add(text.Substring(lastIndex, match.Index - lastIndex));
            lastIndex = match.Index + match.Length;
            var run = new Run(match.Value) {Style = HyperlinkStyle};
            run.MouseDown += RunOnMouseDown;
            Inlines.Add(run);
        }

        Inlines.Add(text.Substring(lastIndex));
    }

    private void RunOnMouseDown(object sender, MouseButtonEventArgs args)
    {
        if (!(sender is Run run)) return;

        var handler = HyperlinkPressed;
        handler?.Invoke(this, new HyperlinkPressedEventArgs(run.Text));
    }
}

public class HyperlinkPressedEventArgs : EventArgs
{
    public readonly Uri Hyperlink;

    public HyperlinkPressedEventArgs(string hyperlink)
    {
        Hyperlink = new Uri(hyperlink);
    }
}

用法:

<Style x:Key="HyperlinkStyle" TargetType="{x:Type Run}">
    <Style.Setters>
        <Setter Property="Foreground" Value="Blue" />
        <Setter Property="TextDecorations" Value="Underline" />
    </Style.Setters>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Cursor" Value="Hand" />
            <Setter Property="Foreground" Value="Orange" />
        </Trigger>
    </Style.Triggers>
</Style>

<htb:HyperlinkTextBlock Background="Transparent"
                        Margin="10,0,0,0"
                        HyperlinkStyle="{StaticResource HyperlinkStyle}"
                        HyperlinkPressed="OnHyperlinkPressed"
                        Text="{Binding Message, NotifyOnTargetUpdated=True}"
                        TextWrapping="Wrap" />

private void OnHyperlinkPressed(object sender, HyperlinkPressedEventArgs args)
{
    System.Diagnostics.Process.Start(args.Hyperlink.OriginalString);
}
c#
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    srvr4vr
    2020-07-12T19:32:51Z2020-07-12T19:32:51Z

    通常由TextBox. 他们将其风格化TextBlock(删除框架,背景等)使其只读,仅此而已。在这里,您可以选择复制。

    更新。我想出了一个快速的解决方案RichTextBox(也许有人会提供更好的,我只是为了):

    public class HyperlinkRichTextBox : RichTextBox
    {
    
        #region CustomText Dependency Property
    
        public static readonly DependencyProperty CustomTextProperty = DependencyProperty.Register("CustomText", typeof(string), typeof(HyperlinkRichTextBox),
            new PropertyMetadata(string.Empty, CustomTextChangedCallback), CustomTextValidateCallback);
    
        public string CustomText
        {
            get => (string)GetValue(CustomTextProperty);
            set => SetValue(CustomTextProperty, value);
        }
    
        private static void CustomTextChangedCallback(
                    DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            ((HyperlinkRichTextBox) obj).Document = GetCustomDocument(e.NewValue as string);
        }
    
        private static bool CustomTextValidateCallback(object value) => value != null;
        #endregion
    
        private const string HttpPrefix = "http://";
    
        private static readonly Regex LinkRegex =
                    new Regex(
                @"([--:А-Яа-я\w?@%&+~#=]*\.[a-zа-я]{2,4}\/{0,2})((?:[?&](?:[А-Яа-я\w]+)=(?:[А-Яа-я\w]+))+|[--:А-Яа-я\w?@%&+~#=]+)?",
                RegexOptions.Compiled);
    
        private static readonly Regex PrefixRegex = 
            new Regex("^(http|ftp)(s)?", RegexOptions.Compiled);
    
        private static FlowDocument GetCustomDocument(string text)
        {
            var document = new FlowDocument();
            var para = new Paragraph {Margin = new Thickness(0)};
    
            var linksMatches = LinkRegex.Matches(text);
    
    
            if (linksMatches.Count == 0)
            {
                para.Inlines.Add(text);
            }
            else
            {
                Match lastMatch = null;
                foreach (Match linksMatch in linksMatches)
                {
                    var previousText = GetPreviousText(text, lastMatch, linksMatch);
    
                    para.Inlines.Add(previousText);
    
                    var link = CreateLink(linksMatch.Value);
                    para.Inlines.Add(link);
                    lastMatch = linksMatch;
                }
                var tail = GetPreviousText(text, lastMatch);
                para.Inlines.Add(tail);
            }
    
            document.Blocks.Add(para);
            return document;
        }
    
        private static Hyperlink CreateLink(string url)
        {
            var link = new Hyperlink
            {
                IsEnabled = true
            };
    
            link.Inlines.Add(url);
    
            link.NavigateUri = PrefixRegex.IsMatch(url)
                ? new Uri(url)
                : new Uri($"{HttpPrefix}{url}");
    
            link.RequestNavigate += (sender, args) => Process.Start(args.Uri.ToString());
    
            return link;
        }
    
        private static string GetPreviousText(string text, Capture lastMatch, Capture currentMatch = null)
        {
            var startIndex = lastMatch != null ? lastMatch.Index + lastMatch.Length : 0;
    
            return currentMatch != null
                ? text.Substring(startIndex, currentMatch.Index - startIndex)
                : text.Substring(startIndex);
        }
    }
    

    我们这样声明:

    <local:HyperlinkRichTextBox BorderThickness="0" Padding="-5" CustomText="{Binding Text}" IsReadOnly="True" IsDocumentEnabled="True">
    

    Padding="-5"添加以便显示与 匹配TextBlock。

    在此处输入图像描述

    而且,当然,可以选择和复制

    在此处输入图像描述

    • 5
  2. Dude36
    2020-07-12T16:33:27Z2020-07-12T16:33:27Z

    我不知道这些方法是否正确,但是您可以在按 RMB(或您的选项)时将类型文本添加到 ToolTip,此链接将被复制。或者用 Heder = "Copy link" 组织一个 MenuItem 并调用 copy 方法。根据代码示例,我不知道该给您什么。

    • -1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5