WPF RichTextBox

I am using WPF RichTextBox to design a ticket layout. The input could also include some code which has special meaning.
e.g. "Ticket Number: <Ticket/>" would print "Ticket Number: 1032" where 1032 is the ticket number issued.

I am using RichTextBox because I need to allow users to change the font of the text. My problem is I can't allow the users to set a different style within a code.
e.g.

Valid: Ticket Number: <Ticket/>
          Ticket Number: <Ticket/>

Not Valid: Ticket Number: <Ticket/>

Note that "<Ticket/>" is a code that corresponds to the ticket number and cannot have different styles within the code.
i.e. If the user underlines part of the code, then the whole code must be underlined.

So in my example:

Ticket Number: <Ticket/>

should be converted automatically to

Ticket Number: <Ticket/>

How can I accomplish this?
LVL 22
ThomasianAsked:
Who is Participating?
 
Bob LearnedCommented:
Here is an example that shows traversing the paragraphs and runs, and getting the style:

How to transfer rich text from a FlowDocument to a FormattedText object
http://www.wpfmentor.com/2009/01/how-to-transfer-rich-text-from.html

private IEnumerable<TextElement> GetRunsAndParagraphs(FlowDocument doc)  
{  
    // use the GetNextContextPosition method to iterate through the  
    // FlowDocument  
      
    for (TextPointer position = doc.ContentStart;  
        position != null && position.CompareTo(doc.ContentEnd) <= 0;  
        position = position.GetNextContextPosition(LogicalDirection.Forward))  
    {  
        if (position.GetPointerContext(LogicalDirection.Forward) ==   
            TextPointerContext.ElementEnd)  
        {  
            // return solely the Runs and Paragraphs. all other elements are   
            // ignored since they aren't supported by FormattedText.  
              
            Run run = position.Parent as Run;  
  
            if (run != null)  
            {  
                yield return run;  
            }  
            else  
            {  
                Paragraph para = position.Parent as Paragraph;  
  
                if (para != null)  
                {  
                    yield return para;  
                }  
            }  
        }  
    }  
}  

Open in new window



public FormattedText GetFormattedText(FlowDocument doc)  
{  
    if (doc == null)  
    {  
        throw new ArgumentNullException("doc");  
    }  
  
    FormattedText output = new FormattedText(  
        GetText(doc),  
        CultureInfo.CurrentCulture,  
        doc.FlowDirection,  
        new Typeface(doc.FontFamily, doc.FontStyle, doc.FontWeight, doc.FontStretch),  
        doc.FontSize,  
        doc.Foreground);  
  
    int offset = 0;  
  
    foreach (TextElement el in GetRunsAndParagraphs(doc))  
    {  
        Run run = el as Run;  
  
        if (run != null)  
        {  
            int count = run.Text.Length;  
  
            output.SetFontFamily(run.FontFamily, offset, count);  
            output.SetFontStyle(run.FontStyle, offset, count);  
            output.SetFontWeight(run.FontWeight, offset, count);  
            output.SetFontSize(run.FontSize, offset, count);  
            output.SetForegroundBrush(run.Foreground, offset, count);  
            output.SetFontStretch(run.FontStretch, offset, count);  
            output.SetTextDecorations(run.TextDecorations, offset, count);  
  
            offset += count;  
        }  
        else  
        {  
            offset += Environment.NewLine.Length;  
        }  
    }  
  
    return output;  
}  

Open in new window

0
 
Bob LearnedCommented:
Are you asking to create readonly regions for the RichTextBox?  What are you using to work with the RichTextBox (i.e. FlowDocument)?
0
 
ThomasianAuthor Commented:
Thanks for you reply.


I am not really very familiar RichTextBox. But is there other ways to work on RichTextBox other than FlowDocument?

Some of the parameters must be editable so I can't really make the code read-only, unless it is possible to make the code read-only while allowing users to change the parameters.

e.g.
<DateTime: MMMM d, yyyy/> would print the current date and time in "MMMM d, yyyy" format.


I also need the code to always have the same style and size.

e.g. It wouldn't make sense if the user entered: <DateTime: MMMM d, yyyy/>


P.S. The RichTextBox will only have one line (no CrLf) if that helps make it simpler.
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

 
Bob LearnedCommented:
I try not to make assumptions, since they are often wrong.

RichTextBox WPF binding
http://stackoverflow.com/questions/343468/richtextbox-wpf-binding

If you are using a RichTextBox, and a FlowDocument, how are you generating the document (Table, Paragraph, Run, ...)?
0
 
ThomasianAuthor Commented:
I have a single paragraph which contains runs (I believe they are added automatically when font/styles are changed).

But I am open to suggestions if there is a better way to implement this
0
 
ThomasianAuthor Commented:
I also posted a related question which describes what I am trying to do.

http:Q_26931026.html

Please also take a look if you have time.

Thanks
0
 
Bob LearnedCommented:
How are font and styles change?  It sounds, now,  like you need to detect when a font or style is changed, and then fix any incorrect conditions.
0
 
ThomasianAuthor Commented:
I haven't really made that part yet since I want to have an overview first of how the whole thing would work. But I will probably have a toolbar to allow the users to change the style and size.
0
 
Bob LearnedCommented:
So, would the user highlight a text region, and click on a toolbar button to change something?  If so, then you should be able to examine the content, to look for text elements that need to be fixed.
0
 
ThomasianAuthor Commented:
>>So, would the user highlight a text region, and click on a toolbar button to change something?
Yes, that's how it should work.

>>If so, then you should be able to examine the content, to look for text elements that need to be fixed.
How do I do that? Can you show me some sample code on how to implement this?

Thanks
0
 
ThomasianAuthor Commented:
How do I extend the style to include the whole code when only part was selected?
0
 
Bob LearnedCommented:
I would say that you would need to start by looking at the number of paragraphs and runs that you have, and see how the RichTextBox works with the FlowDocument when editing the content.  Then, you might be able to see the pattern where a style would be split across multiple runs.  After detecting that condition, it might be as simple as merging two Run elements together.
0
 
ThomasianAuthor Commented:
>>Are you asking to create readonly regions for the RichTextBox?

I suddenly remembered that you mentioned about creating readonly regions in richtextbox. Can you please elaborate on this?
0
 
Bob LearnedCommented:
Here is my interpretation of read-only paragraphs:

 private TableCell AddTableCell(TableRow row, int rowIndex, string text, bool isReadOnly, bool isUnderLine)
        {
            TableCell cell = new TableCell();

            Paragraph paragraph = new Paragraph()
            {
                Focusable = true,
                Tag = isReadOnly,
            };

            Run run = new Run()
            {
                Focusable = true,
                FontFamily = new FontFamily("Tahoma"),
                FontSize = 13,
                Text = text,
            };

            if (isUnderLine)
            {
                run.TextDecorations.Add(TextDecorations.Underline);
            }

            string key = rowIndex + "." + row.Cells.Count;

            if (!this._paragraphs.ContainsKey(key))
            {
                this._paragraphs.Add(key, paragraph);
            }

            paragraph.Inlines.Add(run);

            cell.Blocks.Add(paragraph);

            row.Cells.Add(cell);

            return cell;
        }

    }

Open in new window

0
 
Bob LearnedCommented:
Detecting in the editor:


        private void StepsEditor_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = this.IsParagraphReadOnly(this.StepsEditor.Selection.Start.Paragraph);
        }

        private void StepsEditor_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = this.IsParagraphReadOnly(this.StepsEditor.GetPositionFromPoint(e.GetPosition(this.StepsEditor), true).Paragraph);
        }

        private bool IsParagraphReadOnly(Paragraph paragraph)
        {
            if (paragraph != null)
            {
                if (paragraph.Tag != null && paragraph.Tag is bool && (bool) paragraph.Tag)
                {
                    return true;
                }
            }
            return false;
        }

Open in new window

0
 
ThomasianAuthor Commented:
Thanks for you help.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.