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?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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
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
Exploring SQL Server 2016: Fundamentals

Learn the fundamentals of Microsoft SQL Server, a relational database management system that stores and retrieves data when requested by other software applications.

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
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.