RichTextBox帮助保存*自定义*链接

时间:2012-05-02 02:01:24

标签: c# hyperlink richtextbox customization

我使用找到here的CodeProject在我的rtb中实现了任意链接。链接不是真正的链接,而是单击时查找的数据,并返回有关所单击项目的扩展信息。

这一切都很棒。问题是当我尝试使用RichTextBox1.Rtf方法将数据保存到数据库时链接丢失。我最终得到了文本的值,但是在Rtf中没有保存链接数据。超链接没有Rtf代码吗?有没有解决这个问题的方法?

我正在考虑调整我的方法以更符合this issue,但我不想改变一切,如果我能找到一种方法来保存我的自定义超链接。

任何建议都会很棒!

--------------- UPDATE ----------------

在提交之前,我做了一些挖掘和挖掘this blog article,讨论RTB不保存超链接,所以我想我是SOL。解决这个问题的唯一方法是通过保存隐藏文本框中的文本并将该版本保存到数据库,但这种方式变得笨重。我想我会选择我发现的second option,我想我会发布这个,因为StackOverflow中的数据在这个主题上看起来很渺茫。现在我知道为什么了。

4 个答案:

答案 0 :(得分:1)

由于这是一个旧帖子,我发布此信息仅供参考:

这是comments上同一篇文章的CodeProject中的(某种程度上)近期解决方案:

代码:

/// <summary>
/// This additional code block checks the locations of links
/// and desc. it via a string which contains informations of how many links are there
/// .Split('&')-1 and the select information .Select(.Split('&')[i].Split('-')[0],.Split('&')[i].Split('-')[1])
/// After we select the links we can SetSelectionLink(true) to get our links back.
/// </summary>
public string getLinkPositions()
{
string pos = "";
for (int i = 0; i < this.TextLength; i++)
{
this.Select(i, 1);
int isLink = GetSelectionLink();
if (isLink == 1)
{
//the selected first character is a part of link, now find its last character
for (int j = i + 1; j <= this.TextLength; j++)
{
this.Select(j, 1);
isLink = GetSelectionLink();
if (isLink != 1 || j == this.TextLength)
{
//we found the last character's +1 so end char is (j-1), start char is (i)
pos += (i) + "-" + ((j - 1) - (i - 1)) + "&"; //j-1 to i but i inserted -1 one more so we can determine the right pos
i = j; //cont. from j+1
break; //exit second for cont. from i = j+1 (i will increase on new i value)
}
}
}
}
this.DeselectAll();
return pos;
}
/// <summary>
/// This method generates the links back only created via InsertLink(string text)
/// and overloaded InsertLink(string text,int position)
/// </summary>
/// <param name="pos">the pos string from getLinkPositions</param>
public void setLinkPositions(string pos)
{
string[] positions = pos.Split('&');
for (int i = 0; i < positions.Length - 1; i++)
{
string[] xy = positions[i].Split('-');
this.Select(Int32.Parse(xy[0]), Int32.Parse(xy[1]));
this.SetSelectionLink(true);
this.Select(Int32.Parse(xy[0]) + Int32.Parse(xy[1]), 0);
}
this.DeselectAll();
}

如何使用代码[原文如此]:

  

当你要保存rtf时,保存getLinkPositions()的返回字符串,当你想加载rtf时,只需加载它你的方法,然后使用1st方法的返回字符串来获取链接BAK

     

前:

     

保存:

     
    

一些保存var = richtext.rtf

         

额外保存值= richtext.getLinkPositions();

  
     

加载回来

     
    

richtext.rtf =某些流获取rtf

         

richtext.setLinkPositions(来自的额外保存值)     一些流)

  

答案 1 :(得分:0)

总而言之,Rich Text Boxes不会在.Rtf字段(也不是文本)中保存超链接。保存显示的值,但不保存实际链接。似乎对RTB恕我直言的限制很差。

有很多方法可以解决这种情况,创建自定义链接,例如this fellow did,或者在加载搜索关键字时重新评估您的数据(因为数据永远不会太大而导致冻结,所以我采取的路线)。 / p>

我以前执行此操作的代码如下所示,并在加载时调用:

            foreach (ListViewItem keyword in Keywords.Items)
            {
                System.Text.RegularExpressions.Regex oKeyword = new System.Text.RegularExpressions.Regex(@"\b" + keyword.Text + @"\b");

                foreach (System.Text.RegularExpressions.Match match in oKeyword.Matches(rtb.Text))
                {
                    int index = match.Index;
                    int length = match.Length;

                    rtb.Select(index, length);
                    //This next bit is made available through the use of http://www.codeproject.com/Articles/9196/Links-with-arbitrary-text-in-a-RichTextBox
                    rtb.InsertLink(match.Value);  
                }
            }

答案 2 :(得分:0)

嗯,另一个问题是,hyperlink已被保存&#39;但点击事件和目标丢失了...... 仅恢复格式和行为(光标更改)。 如果你操作这个恢复的文本块,那一切都搞砸了。 因此,在进行任何“恢复”之前操作,您需要清除<hyperlink>内容。

Prajakta Joshi为自动检测超链接做了一个例子 - 它还包含一个清理例程: http://blogs.msdn.com/b/prajakta/archive/2006/10/17/autp-detecting-hyperlinks-in-richtextbox-part-i.aspx

干杯,斯蒂芬

答案 3 :(得分:0)

由于Hyperlink标签不会因保存而丢失,因此另一个approch将扫描加载的文档以查找这些标记并重新应用它的属性 - 单击事件和导航uri。

void restoreHyperlinks()
{
    TextRange tr = new TextRange(_richTextBox.Document.ContentStart, _richTextBox.Document.ContentEnd);
    TextPointer tp = tr.Start;
    bool bFound = false;
    foreach (System.Text.RegularExpressions.Match match in UrlRegex.Matches(tr.Text))
    {
        if (tp == null)
            tp = tr.Start;
        bFound = false;
        while (tp != null && !bFound)
        {

            if (tp.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
            {
                string textRun = tp.GetTextInRun(LogicalDirection.Forward);
                int indexInRun = textRun.IndexOf(match.Value);
                if (indexInRun > -1)
                {
                    bFound = true;
                    Inline parent = tp.Parent as Inline;
                    while (parent != null && !(parent is Hyperlink))
                    {
                        parent = parent.Parent as Inline;
                    }
                    if (parent is Hyperlink)
                    {
                        Hyperlink hyperlink = (Hyperlink)parent;
                        if (isHyperlink(match.Value))
                        {
                            Uri uri = new Uri(match.Value, UriKind.RelativeOrAbsolute);
                            if (!uri.IsAbsoluteUri)
                            {
                                uri = new Uri(@"http://" + match.Value, UriKind.Absolute);
                            }
                            if (uri != null)
                            {
                                hyperlink.NavigateUri = uri;
                                hyperlink.Click += Hyperlink_Click;
                            }
                        }
                    }
               }

            }
            tp = tp.GetNextContextPosition(LogicalDirection.Forward);
        }
    }

}

正则表达式是:

private static readonly System.Text.RegularExpressions.Regex UrlRegex = new System.Text.RegularExpressions.Regex(@"(?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&amp;(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?");

isHyperlink是检查URL的另一种方法 - 代码取自: http://marcangers.com/detect-urls-add-hyperlinks-wpf-richtextbox-automatically/

希望这有帮助! 干杯,斯蒂芬