DocumentPosition pos =
new
DocumentPosition(
this
.radRichTextBox.Document.CaretPosition);
pos.MoveToCurrentWordStart();
this
.radRichTextBox.Document.Selection.SetSelectionStart(pos);
pos.MoveToCurrentWordEnd();
this
.radRichTextBox.Document.Selection.AddSelectionEnd(pos);
And then work with selected word. Or just replace word in position.
The result should be (3 consecutive Shift+F3):
word --(Shift+F3)-> Word --(Shift+F3)-> WORD --(Shift+F3)-> word
7 Answers, 1 is accepted
You could use both of the approaches - registering custom command or handling PreviewEditorKeyDown event, for example:
public
partial
class
MainDemoControl : UserControl
{
public
static
RoutedCommand ToggleCaseRoutedCommand =
new
RoutedCommand();
public
MainDemoControl()
{
RadRichTextBox.RegisterCommand(MainDemoControl.ToggleCaseRoutedCommand, Key.F3, ModifierKeys.Shift);
InitializeComponent();
this
.radRichTextBox.CommandBindings.Add(
new
CommandBinding(MainDemoControl.ToggleCaseRoutedCommand, Executed, CanExecute));
}
private
void
Executed(
object
sender, ExecutedRoutedEventArgs e)
{
this
.radRichTextBox.BeginUndoGroup();
if
(
this
.radRichTextBox.Document.Selection.IsEmpty)
{
DocumentPosition pos =
new
DocumentPosition(
this
.radRichTextBox.Document.CaretPosition);
pos.MoveToCurrentWordStart();
this
.radRichTextBox.Document.Selection.SetSelectionStart(pos);
pos.MoveToCurrentWordEnd();
this
.radRichTextBox.Document.Selection.AddSelectionEnd(pos);
}
else
if
(
this
.radRichTextBox.Document.Selection.Ranges.Count > 1)
{
// If multirange selection is present, use only the first range.
DocumentPosition start =
new
DocumentPosition(
this
.radRichTextBox.Document.Selection.Ranges.First.StartPosition);
DocumentPosition end =
new
DocumentPosition(
this
.radRichTextBox.Document.Selection.Ranges.First.EndPosition);
this
.radRichTextBox.Document.Selection.SetSelectionStart(start);
this
.radRichTextBox.Document.Selection.AddSelectionEnd(end);
}
string
selectedText =
this
.radRichTextBox.Document.Selection.GetSelectedText();
this
.radRichTextBox.Insert(selectedText.ToUpper());
this
.radRichTextBox.EndUndoGroup();
}
private
void
CanExecute(
object
sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute =
true
;
}
Don't hesitate to contact us if you have other questions.
Regards,
Boby
Telerik
Hi,
This solution works only partially. It works only if you use a shortcut like Shift F3 and it clears the formatting.
The toggle functionality should change not only to upper but also from all upper to all lower and from lower to first upper. Fortunately I don't need toggle.
I need just to upper and to lower but not from shortcut but from context menu. Unfortunately if you use context menu the selection is lost. (it is visible, but the statement Document.Selection.IsEmpty returns true). I call it a bug.
Then there is the lost of formatting if you use
string selectedText = this.radRichTextBox.Document.Selection.GetSelectedText();
this.radRichTextBox.Insert(selectedText.ToUpper());
I replaced it with
foreach (var box in Document.Selection.GetSelectedBoxes().ToList())
{
if (!box.IsFormattingSymbol)
box.Text = box.Text.ToUpper();
}
And it almost works (from shortcut not from context menu). You need to scroll up to hide affected text and then scroll down to redraw it. I tried with Invalidate but no luck. Also undo doesn't work.
So my questions are:
Is there a way to force document to be redrawn?
Is there a way to use context menu and have access to selection?
Regards,
Daniel
You are right, the solution I proposes was only a workaround, and is not considering formatting of the text.
The best approach would be to get the selected spans from the selected span layout boxes, modify their text with ToUpper/ToLower where needed and then re-insert the spans. This could be tricky tough, as you would need mapping between the spans and the plain text representation, moreover some of the spans may be only partially selected.
Using the RadRichTextBox.InsertInine method to insert spans and BeginUndoGroup/EndUndoGroup methods will ensure that the history will be preserved, and Undo/Redo would work as expected.
There is a public item in the feedback portal regarding the change case command here:
Change Case Command
where you can vote for this feature and track eventual implementation.
For the context menu, you can customize it (add custom elements) using one of the approaches described in the Context Menu help article. I have performed some tests and the selection seems correctly reported as not empty (for example in a ContextMenu.Showing event handler).
Regards,
Boby
Telerik
Thanks,
I've fixed the issue with selection.
I tried to use InsertInline but it works only if you select one whole span.
As I asked before. IS there a way to force document to be redrawn?
Regards,
Daniel
You could, but I would not recommend using the approach with setting the text directly on the layout boxes, because of the following reasons:
- This relies on an implementation detail - namely that setting text on a layout box would affect the underlying span. For historical reasons the API of the layout model is too "open", exposing properties (like set_Text) which are not very user-friendly and should not be used in normal circumstances.
- The layout would be only partially invalidated - for example the last words could be trimmed as the parent paragraph layout box is not notified for the change.
- Setting properties directly on the document model elements (and not through RadRichTextBox or RadDocumentEditor) is not recommended as it could be easy to broke the underlying model (some validation checks are skipped) and moreover it resets the document history.
- Without more complex logic, you would get a behavior similar to the approach suggested by me (with using InsertInline) - if only parts of the span box are selected, you would change the case of the whole span box.
Otherwise, the most easiest way to simulate what happens on scroll is to invoke the RecreateUI method of the active document presenter:
this
.radRichTextBox.ActiveEditorPresenter.RecreateUI();
Regards,
Boby
Telerik