Results 1 to 25 of 25

Thread: WPF RichTextBox Question

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    WPF RichTextBox Question

    Recently I have decided to switch from the Forms RichTextBox to the WPF RichTextBox for my chat client. I've been reading up on applying properties to the text. I've found that I can use 2 methods to doing this.

    Method 1:
    Code:
    TextRange tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
    tr.Text = "Some Text Here";
    tr.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
    Method 2:
    Code:
    Run r = new Run("Some Text Here");
    r.FontFamily = new System.Windows.Media.FontFamily("Tahoma");
    r.FontSize = 12;
    r.FontStyle = System.Windows.FontStyles.Normal;
    r.FontWeight = System.Windows.FontWeights.Regular;
    r.Foreground = System.Windows.Media.Brushes.SteelBlue;
    para.Inlines.Add(r);
    At the moment I am using method 2. The server my client works uses a style-like tags around text to specify the color, font, weight, ect. So for each group of text in a style tag I create and add a new run object to the paragraph. My problem comes when I need to loop through the run to set hyperlinks and insert emoticons. Since all the text is not in a single run object I find that if a user uses a gradient (text fader) the style tags may open or close inside of a hyperlink or the emoticons text.

    Eg. [style co:#D6D6D6]www.some[/style]site.com

    "www.some" would be a run object and "site.com" would be another.

    What I need to do is to figure how to either apply multiple properties to different segments of a run object or find a way to join multiple run objects. Unless there is some other way I have overlooked. I am still very new to WPF.

    Here is a post with the method I use to add emoticons that shows how I loop through the run object.

    Help with embedding images into a RichTextbox

  2. #2
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    Your best bet is to pull all the content out into an array list or list of strings do the formatting their and then build a flow document (which is what the RTB uses) each time. That way your RUN's are re writen each time. Also rather than loop through the runs you could just apply some REGEX queries to replace each smilie code with the inline code for the given smilie. Im in work at the moment but I will post some code on how to do that later (around 7pm) for ya!

  3. #3
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    Ok so I need to find out what exactly which way you are doing what your doing. So in your application do I type into a text box and then you update the RTB? Give me a run through and Il give you a hand?

  4. #4

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    On self input yes. Say I type in "Hello! :P" and my font I have selected is Tahoma and the color is black it will pass the folowing string to be formatted to the rtb.

    [style co:#000000;b;]Tewl : [/style][style ff:Tahoma;co:#000000]Hello! :P[/style]

  5. #5
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    Ok sorry this took so long, I was playing with code. Now if you are using an RTB for your input box and another RTB for your "display" you do not need to use style tags or anything else for that matter. Consider that a flow document is simply a Xaml rendering control. This means that its content is all written in Xaml. Xaml is of course text. So if we use this nifty piece of code which is basically your method 1 extended:

    Code:
            Dim tr As New TextRange(PasteBox.Document.ContentStart, PasteBox.Document.ContentEnd)
            Dim ms As New MemoryStream
            tr.Save(ms, DataFormats.Xaml)
            Dim TextArray As String = ASCIIEncoding.Default.GetString(ms.ToArray())
    and text array now contains an array of your text with the Xaml mark-up included as a plain string. the content is already grouped with a section object from what I can gather from tests. So you would simply need to add this array as a section to your display window.

    Now because you have the FULL power of flow documents you can now do something that most messengers cant do. you can make fantasticly rich content. so smilies embedded video, fancy lists! This all of course depends on your server construction but it is all technically possible. have fun with it!

  6. #6

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    Thanks
    Last edited by Tewl; Feb 15th, 2009 at 12:58 PM.

  7. #7
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    Does it work for you?

  8. #8

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    I'm kinda of lost as to how to insert images and clickable urls with this method

  9. #9
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    This is the flow document class. If you look towards the end you will see the different classes you can use with a flow document. The ones you need to look at is link and inline ui container.

  10. #10

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    I was having an issue understanding the TextPointers but I think I have it now.

    Code:
            private void button1_Click(object sender, EventArgs e)
            {
                TextRange tr = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
                TextPointer stp = rtb.Document.ContentStart.GetPositionAtOffset(tr.Text.Length - 2);
    
                tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
                tr.Text = "\rSome :) text here";
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, System.Windows.Media.Brushes.Black);
                tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
                tr.Text = "\rSome more text :) here";
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, System.Windows.Media.Brushes.Red);
                tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
                tr.Text = "\rmore text here :)";
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, System.Windows.Media.Brushes.SteelBlue);
               
                BitmapImage bi;
    
                tr = new TextRange(stp, rtb.Document.ContentEnd);
    
                string emoticonText = GetEmoticonText(tr.Text);
    
                TextPointer tp = stp;
    
                while (emoticonText != string.Empty)
                {
                    while (!tp.GetTextInRun(LogicalDirection.Forward).StartsWith(emoticonText))
                        tp = tp.GetNextInsertionPosition(LogicalDirection.Forward);
    
                    tr = new TextRange(tp, tp.GetPositionAtOffset(emoticonText.Length));
    
                    tr.Text = string.Empty;
    
                    bi = new BitmapImage();
                    bi.BeginInit();
                    bi.UriSource = new Uri(mappings[emoticonText]);
                    bi.DecodePixelWidth = 26;
                    bi.EndInit();
    
                    System.Windows.Controls.Image image = new System.Windows.Controls.Image();
                    image.Width = 26;
                    image.Stretch = System.Windows.Media.Stretch.None;
                    image.Source = bi;
    
                    new InlineUIContainer(image, tp);
    
                    tr = new TextRange(tp, rtb.Document.ContentEnd);
    
                    if (tr.Text == string.Empty)
                        break;
                    else
                        emoticonText = GetEmoticonText(tr.Text);
                }
            }
    
            private string GetEmoticonText(string text)
            {
                string match = string.Empty;
                int lowestPosition = text.Length;
    
                foreach (KeyValuePair<string, string> pair in mappings)
                {
                    if (text.Contains(pair.Key))
                    {
                        int newPosition = text.IndexOf(pair.Key);
    
                        if (newPosition < lowestPosition)
                        {
                            match = pair.Key;
                            lowestPosition = newPosition;
                        }
                    }
                }
                return match;
            }
    I am curious as to why this returns a length of 2 when the RTB is empty.

    TextRange tr = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
    MessageBox.Show(tr.Text.Lengh.ToString());

    Other than that, now all I have to do is write a function to convert urls tp clickable hyperlinks.

  11. #11

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    Ok my next issue with this is putting in the Hyperlinks

    Code:
                string uriText = GetUriText(tr.Text);
    
                Hyperlink h;
    
                while (uriText != string.Empty)
                {
                    while (!tp.GetTextInRun(LogicalDirection.Forward).StartsWith(uriText))
                        tp = tp.GetNextInsertionPosition(LogicalDirection.Forward);
    
                    h = new Hyperlink(tp, tp.GetPositionAtOffset(uriText.Length));
    
                    tp = tp.GetPositionAtOffset(uriText.Length);
    
                    tr = new TextRange(tp, rtb.Document.ContentEnd);
    
                    if (tr.Text != string.Empty)
                        uriText = GetUriText(tr.Text);
                }
    Code:
            private string GetUriText(string text)
            {
                string match = string.Empty;
                Regex r = new Regex("(?:^|[\\s\\[\\]\\}\\{\\(\\)\\\'\\\"<>])((?:(?:https?|gopher|ftp|file|irc):\\/\\/|www\\.)[a-zA-Z0-9\\.\\-=;&%\\?]+(?:\\/?[a-zA-Z0-9\\.\\-=;&%\\?]*)*)");
                if (r.IsMatch(text))
                {
                    Match m = r.Match(text);
                    match = m.Groups[1].Value;
                }
                return match;
            }
    After I run this I get a squiggly line under the url but it is not clickable nor does it fire any events when I add a click event to the hyperlink object.

  12. #12

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    Screenshot: Removed bandwidth issue
    Last edited by Tewl; Mar 4th, 2009 at 10:45 PM.

  13. #13
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    Hmmmm, something is breaking your Links alright. You need to pull the xaml out and have a look to see if they are being created properly.

  14. #14

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    hmmm. I'm kind of lost as to what to do at this point.

    Code:
    <Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve" TextAlignment="Left" LineHeight="Auto" IsHyphenationEnabled="False" xml:lang="en-us" FlowDirection="LeftToRight" NumberSubstitution.CultureSource="User" NumberSubstitution.Substitution="AsCulture" FontFamily="Microsoft Sans Serif" FontStyle="Normal" FontWeight="Normal" FontStretch="Normal" FontSize="11" Foreground="#FF000000" Typography.StandardLigatures="True" Typography.ContextualLigatures="True" Typography.DiscretionaryLigatures="False" Typography.HistoricalLigatures="False" Typography.AnnotationAlternates="0" Typography.ContextualAlternates="True" Typography.HistoricalForms="False" Typography.Kerning="True" Typography.CapitalSpacing="False" Typography.CaseSensitiveForms="False" Typography.StylisticSet1="False" Typography.StylisticSet2="False" Typography.StylisticSet3="False" Typography.StylisticSet4="False" Typography.StylisticSet5="False" Typography.StylisticSet6="False" Typography.StylisticSet7="False" Typography.StylisticSet8="False" Typography.StylisticSet9="False" Typography.StylisticSet10="False" Typography.StylisticSet11="False" Typography.StylisticSet12="False" Typography.StylisticSet13="False" Typography.StylisticSet14="False" Typography.StylisticSet15="False" Typography.StylisticSet16="False" Typography.StylisticSet17="False" Typography.StylisticSet18="False" Typography.StylisticSet19="False" Typography.StylisticSet20="False" Typography.Fraction="Normal" Typography.SlashedZero="False" Typography.MathematicalGreek="False" Typography.EastAsianExpertForms="False" Typography.Variants="Normal" Typography.Capitals="Normal" Typography.NumeralStyle="Normal" Typography.NumeralAlignment="Normal" Typography.EastAsianWidths="Normal" Typography.EastAsianLanguage="Normal" Typography.StandardSwashes="0" Typography.ContextualSwashes="0" Typography.StylisticAlternates="0"><Paragraph><Run>
    Some </Run><Run> </Run><Run> text here</Run><Run Foreground="#FFFF0000">
    Some </Run><Hyperlink Foreground="#FF808080" TextDecorations="Underline"><Run Foreground="#FFFF0000">http://www.microsoft.com</Run></Hyperlink><Run Foreground="#FFFF0000"> more text </Run><Run> </Run><Run Foreground="#FFFF0000"> here</Run><Run Foreground="#FF4682B4">
    more text here </Run><Run> </Run></Paragraph></Section>
    Last edited by Tewl; Feb 20th, 2009 at 03:09 PM.

  15. #15
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    I see the issue, your link doesnt have a navigateuri in it it only has text. see this http://msdn.microsoft.com/en-us/libr...hyperlink.aspx for usage.

  16. #16

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    I get the same result if I set the NavigateUri as well

    Code:
    h = new Hyperlink(tp, tp.GetPositionAtOffset(uriText.Length));
    h.NavigateUri = new Uri(uriText);
    Code:
    <Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve" TextAlignment="Left" LineHeight="Auto" IsHyphenationEnabled="False" xml:lang="en-us" FlowDirection="LeftToRight" NumberSubstitution.CultureSource="User" NumberSubstitution.Substitution="AsCulture" FontFamily="Microsoft Sans Serif" FontStyle="Normal" FontWeight="Normal" FontStretch="Normal" FontSize="11" Foreground="#FF000000" Typography.StandardLigatures="True" Typography.ContextualLigatures="True" Typography.DiscretionaryLigatures="False" Typography.HistoricalLigatures="False" Typography.AnnotationAlternates="0" Typography.ContextualAlternates="True" Typography.HistoricalForms="False" Typography.Kerning="True" Typography.CapitalSpacing="False" Typography.CaseSensitiveForms="False" Typography.StylisticSet1="False" Typography.StylisticSet2="False" Typography.StylisticSet3="False" Typography.StylisticSet4="False" Typography.StylisticSet5="False" Typography.StylisticSet6="False" Typography.StylisticSet7="False" Typography.StylisticSet8="False" Typography.StylisticSet9="False" Typography.StylisticSet10="False" Typography.StylisticSet11="False" Typography.StylisticSet12="False" Typography.StylisticSet13="False" Typography.StylisticSet14="False" Typography.StylisticSet15="False" Typography.StylisticSet16="False" Typography.StylisticSet17="False" Typography.StylisticSet18="False" Typography.StylisticSet19="False" Typography.StylisticSet20="False" Typography.Fraction="Normal" Typography.SlashedZero="False" Typography.MathematicalGreek="False" Typography.EastAsianExpertForms="False" Typography.Variants="Normal" Typography.Capitals="Normal" Typography.NumeralStyle="Normal" Typography.NumeralAlignment="Normal" Typography.EastAsianWidths="Normal" Typography.EastAsianLanguage="Normal" Typography.StandardSwashes="0" Typography.ContextualSwashes="0" Typography.StylisticAlternates="0"><Paragraph><Run>
    Some </Run><Run> </Run><Run> text here</Run><Run Foreground="#FFFF0000">
    Some </Run><Hyperlink Foreground="#FF808080" NavigateUri="http://www.microsoft.com" TextDecorations="Underline"><Run Foreground="#FFFF0000">http://www.microsoft.com</Run></Hyperlink><Run Foreground="#FFFF0000"> more text </Run><Run> </Run><Run Foreground="#FFFF0000"> here</Run><Run Foreground="#FF4682B4">
    more text here </Run><Run> </Run></Paragraph></Section>

  17. #17
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    Try remove the runs manually and then put the xaml code back into the RTB via a section and see does it click then I think they are causing the issue.

  18. #18

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    Doing that removes all of the formatting

  19. #19
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    I know but for the moment we just need to find out if it is affecting the click ability of the link.

  20. #20

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    Same result. Link is now grey. Updated screenshot above.

  21. #21
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    and still not clickable. This may sound stupid but try to control click the link. Otherwise im out of ideas for the moment.

  22. #22

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    I apparently the click event wouldnt fire. MouseLeftButtonDown however does. This fixes my main issue, now I just have to figure out how to insert the hyperlink to to text that is split into 2 seperate runs

    <Run>http://www.micro</Run><Run>soft.com</Run>

    Code:
    tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
    tr.Text = "\rSome http://www.micro";
    tr.ApplyPropertyValue(TextElement.ForegroundProperty, System.Windows.Media.Brushes.Red);
    tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
    tr.Text = "soft.com more text :) here";
    tr.ApplyPropertyValue(TextElement.ForegroundProperty, System.Windows.Media.Brushes.SteelBlue);
    Last edited by Tewl; Mar 4th, 2009 at 10:46 PM.

  23. #23
    Frenzied Member
    Join Date
    Jul 2008
    Location
    Rep of Ireland
    Posts
    1,380

    Re: WPF RichTextBox Question

    One of your objects is not initialised. IE

    MyVar VAR = new VAR;

  24. #24

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    It's the TextPointer that is null; it becomes null during the loop.

  25. #25

    Thread Starter
    Addicted Member
    Join Date
    Jun 2003
    Location
    Birmingham, AL
    Posts
    188

    Re: WPF RichTextBox Question

    I was experimenting with a new method of inserting the text and managed to get this which works really well altho it doesn't fix my issue with inserting urls that are in 2 different Runs but that is a minor issue.

    Code:
            private void InsertHyperlink(TextPointer position)
            {
                string match = string.Empty;
                Regex r = new Regex("(?:^|[\\s\\[\\]\\}\\{\\(\\)\\\'\\\"<>])((?:(?:https?|gopher|ftp|file|irc):\\/\\/|www\\.)[a-zA-Z0-9\\.\\-=;&%\\?]+(?:\\/?[a-zA-Z0-9\\.\\-=;&%\\?]*)*)");
                
                Hyperlink h;
    
                while (position != null)
                {
                    if (position.CompareTo(this.Document.ContentEnd) == 0)
                    {
                        break;
                    }
                    if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                    {
                        String text = position.GetTextInRun(LogicalDirection.Forward);
                        Int32 indexInRun = -1;
                        if (r.IsMatch(text))
                        {
                            Match m = r.Match(text);
                            match = m.Groups[1].Value;
                            indexInRun = m.Groups[1].Index;
                        }
    
                        if (indexInRun >= 0)
                        {
                            position = position.GetPositionAtOffset(indexInRun);
                            h = new Hyperlink(position, position.GetPositionAtOffset(match.Length));
                            h.Tag = match;
                            h.Foreground = Brushes.Blue;
                            h.TextDecorations = TextDecorations.Underline;
                            h.Cursor = System.Windows.Input.Cursors.Hand;
                            h.MouseLeftButtonDown += new MouseButtonEventHandler(h_MouseLeftButtonDown);
                            position = position.GetPositionAtOffset(match.Length);
                        }
                        else
                        {
                            position = position.GetPositionAtOffset(text.Length);
                        }
                    }
                    else
                    {
                        position = position.GetNextContextPosition(LogicalDirection.Forward);
                    }
                }
            }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width