This is a migrated thread and some comments may be shown as answers.

Dynamically switching icons in document to text

3 Answers 110 Views
RichTextBox
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Chris
Top achievements
Rank 1
Chris asked on 12 Jan 2011, 07:06 PM
I have a requirement where I need to switch an icon that I have inserted using the inlineuicontainer to text. Currently a user inserts what we are calling a note. An icon is inserted at the cursor position to show that there is a note at this position. Mousing over this icon displays the notes value. Now what I am trying to do is to have a button that would toggle every note that is in the document to hide the inlineiocontainer and to show the notes text value. I currently have this working but the text is not showing up where I would expect it to. I seem to be doing something wrong with the position because I can set the position when the note is inserted and then when I call ShowText the position is changed and it inserts everything in one location.

public void InsertAnnotation(string GUID, String noteText)
        {
            string url = "/Telerik.Windows.Controls.RichTextBoxUI;component/Images/MSOffice/16/FindNextSpellingError.png";
  
            Image annotationIcon = new Image();
            annotationIcon.Source = new BitmapImage(new Uri(url, UriKind.RelativeOrAbsolute));
  
            CustomHyperLinkButton link = new CustomHyperLinkButton { Width = 20, Height = 20, Content = annotationIcon, Name = "Note_" + GUID,  NoteContent = noteText, };
  
            DocumentPosition position = new DocumentPosition(editor.Document);
  
            position = editor.Document.CaretPosition;
  
            link.LocationInDoc = position;
  
            link.showingText = false;
  
            TextBox textBox = new TextBox { Width = 295, Height = 345, Text = noteText, TextWrapping = TextWrapping.Wrap};
  
            RadWindow radWindow = new RadWindow {Width = 300, Height = 300, Header = "Note", Content = textBox, Visibility = Visibility.Visible };
  
            ToolTipService.SetToolTip(link, radWindow);
  
            link.Click += AnnotationLinkButton_Click;
  
            InlineUIContainer container = new InlineUIContainer
                                              {
                                                  UiElement = link,
                                                  Width = 20,
                                                  Height = 20d,
                                              };
  
            editor.InsertInline(container);
  
            position.Reset();
        }
  
private void ShowText(object sender, RoutedEventArgs e)
        {
            List<InlineUIContainer> links = editor.Document.EnumerateChildrenOfType<InlineUIContainer>().ToList();
  
            foreach (var inlineUiContainer in links)
            {
                CustomHyperLinkButton btn = (CustomHyperLinkButton) inlineUiContainer.UiElement;
  
                if (!btn.showingText)
                {
                    btn.Visibility = Visibility.Collapsed;
  
                    Span span = new Span("{ " + btn.NoteContent + " }");
  
                    editor.Document.InsertInline(span, btn.LocationInDoc);
  
                    btn.showingText = true;
                }
            }
        }

3 Answers, 1 is accepted

Sort by
0
Iva Toteva
Telerik team
answered on 13 Jan 2011, 02:17 PM
Hello Chris,

Currently RadRichTextBox does not fully support your scenario. We will take it into consideration in the future, but as of now, a little modification of your code solves the issues you have encountered:

public void InsertAnnotation(String noteText)
{
    string url = "/Telerik.Windows.Controls.RichTextBoxUI;component/Images/MSOffice/16/FindNextSpellingError.png";
    Image annotationIcon = new Image();
    annotationIcon.Source = new BitmapImage(new Uri(url, UriKind.RelativeOrAbsolute));
    CustomHyperLinkButton link = new CustomHyperLinkButton { Width = 20, Height = 20, Content = annotationIcon, NoteContent = noteText, };
    link.Click += ShowText;
    InlineUIContainer container = new InlineUIContainer
    {
        UiElement = link,
        Width = 20,
        Height = 20d,
    };
    editor.InsertInline(container);
}
 
private void ShowText(object sender, RoutedEventArgs e)
{
    CustomHyperLinkButton pressedButton = sender as CustomHyperLinkButton;
    List<InlineUIContainer> links = editor.Document.EnumerateChildrenOfType<InlineUIContainer>().ToList();
    foreach (var container in links)
    {
        CustomHyperLinkButton btn = container.UiElement as CustomHyperLinkButton;
        if (btn == pressedButton )
        {
            Span span = new Span("{ " + btn.NoteContent + " }");
            var inlineBox = container.FirstLayoutBox as InlineLayoutBox;
            if (inlineBox != null)
            {
                editor.Document.CaretPosition.MoveToInline(inlineBox, 0);
                editor.Document.InsertInline(span);                   
            }
            editor.Document.CaretPosition.MoveToNextSpanBox();
            btn.Visibility = Visibility.Collapsed;
            container.Height = 0;
            container.Width = 0;
       //   this.editor.Delete(true); //if you want to delete the InlineUIContainer with the button
        }
        this.editor.UpdateEditorLayout(); //this is needed only if you set the container.Height and Width properties
    }
}

Note that DocumentPosition is a reference type and 
position = editor.Document.CaretPosition;
creates an alias for the CaretPosition and it changes when the caret position moves. What you need most probably is:
position = new DocumentPosition(editor.Document.CaretPosition);

Saving the DocumentPosition when creating the CustomHyperLinkButton is also a tricky moment, as this DocumentPosition will not be anchored to the same position in the document when the document content changes.
Try this approach and let us know if this solution does not match your requirements or you experience any further difficulties.

All the best,
Iva
the Telerik team
Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
0
Chris
Top achievements
Rank 1
answered on 13 Jan 2011, 07:43 PM
Thank you for your help with this. This was a lot of help. I will share what I came up with as my solution to the problem. It is pretty much code for annotating a document. Let me know if you see anyway to improve upon it.

private void ToggleCommentView(object sender, RoutedEventArgs e)
        {
            List<InlineUIContainer> links = editor.Document.EnumerateChildrenOfType<InlineUIContainer>().ToList();
  
            List<Paragraph> paragraphs = editor.Document.EnumerateChildrenOfType<Paragraph>().ToList();
  
            List<Span> spans = editor.Document.EnumerateChildrenOfType<Span>().ToList();
  
            if (!ShowingComments)
            {
                foreach (var inlineUiContainer in links)
                {
                    CustomHyperLinkButton btn = (CustomHyperLinkButton) inlineUiContainer.UiElement;
  
                    if (btn.AnnotationType == Constants.AnnotationTypes.AnnotationType.Comment)
                    {
                        Span span = new Span("[ " + btn.CommentContent + " ]")
                                        {
                                            ForeColor = Colors.Red,
                                            FontStyle = FontStyles.Italic,
                                            FontSize = 10
                                        };
                        var inlineBox = inlineUiContainer.FirstLayoutBox as InlineLayoutBox;
                        if (inlineBox != null)
                        {
                            editor.Document.CaretPosition.MoveToInline(inlineBox, 0);
                            editor.Document.InsertInline(span);
                        }
                        editor.Document.CaretPosition.MoveToNextSpanBox();
                        btn.Visibility = Visibility.Collapsed;
                        inlineUiContainer.Height = 0;
                        inlineUiContainer.Width = 0;
                    }
                }
  
                this.editor.UpdateEditorLayout();
                ShowingComments = true;
            }
            else
            {
                foreach (var inlineUiContainer in links)
                {
                    CustomHyperLinkButton btn = (CustomHyperLinkButton) inlineUiContainer.UiElement;
  
                    editor.Document.CaretPosition.MoveToNextSpanBox();
                    btn.Visibility = Visibility.Visible;
                    inlineUiContainer.Height = 20;
                    inlineUiContainer.Width = 20d;
  
                    foreach (var paragraph in paragraphs)
                    {
                        foreach (var span in spans)
                        {
                            if (span.Text == "[ " + btn.CommentContent + " ]")
                                paragraph.Inlines.Remove(span);
                        }
                    }
                }
  
                this.editor.UpdateEditorLayout();
                ShowingComments = false;
            }
        }
0
Iva Toteva
Telerik team
answered on 18 Jan 2011, 08:55 AM
Hello Chris,
Your code looks OK to me with just a few remarks.
  1. When you are removing the span and substituting it for the button, you are making some unneeded operations (trying to remove a span from all paragraphs, instead of its own only). The following optimization can be applied:
  2. else
    {
        foreach (var inlineUiContainer in links)
        {
            CustomHyperLinkButton btn = (CustomHyperLinkButton)inlineUiContainer.UiElement;
            editor.Document.CaretPosition.MoveToNextSpanBox();
            btn.Visibility = Visibility.Visible;
            inlineUiContainer.Height = 20;
            inlineUiContainer.Width = 20;
     
            Paragraph paragraph = inlineUiContainer.Parent as Paragraph;
            foreach (var span in paragraph.EnumerateChildrenOfType<Span>())
            {
                if (span.Text == "[ " + btn.ActualHeight + " ]")
                {
                    paragraph.Inlines.Remove(span);
                }
            }
        }
        this.editor.UpdateEditorLayout();
        ShowingComments = false;
    }
  3.  If you are not using RadRichTextBox in read only mode, you might encounter unexpected behavior. Copy-pasting of InlineUIContainers will not work properly, as you cannot add one and the same button two times in the same document (both when the button is visible and collapsed).
If you have other questions, do not hesitate to contact us again.

Regards,
Iva
the Telerik team
Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
Tags
RichTextBox
Asked by
Chris
Top achievements
Rank 1
Answers by
Iva Toteva
Telerik team
Chris
Top achievements
Rank 1
Share this question
or