This is my code for changing the font style to normal. But my problem is that it changes all of the text in the RichTextBox. What I want is that it will change the selected text and change the style of the text I will write.
private void italicToggle_Unchecked(object sender, RoutedEventArgs e)
{
text.Selection.ApplyPropertyValue(FontStyleProperty, FontStyles.Normal);
text.FontStyle = FontStyles.Italic;
}
A textbox contains only "unformatted text." That is, you can set the font or font style, etc for the whole textbox but not for a portion (selection). To be able to change a portion of text you must use a RichTextBox (RichTextBox Class). And see this for an overview (RichTextBox Overview).
Related
I have a RichTextBox. I'm working on changing the SelectionBackColor only of the selected text.
Then, I have a ToolStripMenuItem(let's call it 'buttonA' for now) which is responsible to change the SelectionBackColor of the selected text. The problem I'm facing is after I click buttonA, the background color of the selected text in the RichTextBox can be successfully done. However, when I add some other characters or text right after the changed background color text, it doesn't use the default background color. Instead, it continues to use the same background color as assigned from buttonA, which I don't want to happen.
At first, I thought that my start index and end index of the selected text was problematic. But, I don't think there's any problems in its codes. Below shows the code example:
SolidBrush textBgCol; //a variable to keep color
this.richTextBox1.Select = this.richTextBox1.SelectionStart, this.richTextBox1.SelectionLength;
this.richTextBox1.SelectionBackColor = Color.FromArgb(textBgCol.Color.A, textBgCol.Color.R, textBgCol.Color.G, textBgCol.Color.B);
One of my efforts was to change the SelectionBackColor to default in the KeyDown event of richTextBox1. However, the background color of the new or successive characters and text were still the same as assigned from buttonA. Below shows the code example:
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
this.richTextBox1.SelectionBackColor = default;
}
I've also tried to refer to this but, I don't think it helps me to solve my case here.
Other than that, just to confirm that my richTextBox1's SelectionStart and SelectionLength were okay, I've even referred to these: ref1, ref2, and ref3.
May I know any other workarounds for this please? Or, were there anything inside my codes that I've missed?
Based on comment by #Jimi:
I just need to change the codes in my richTextBox1's KeyDown event handler to:
if(richTextBox1.SelectionBackColor != richTextBox1.BackColor)
{
richTextBox1.SelectionBackColor = richTextBox1.BackColor;
}
Below shows the demo:
Thanks!
Basically in my app I have a RichEditBox which is required to save its data on TextChanged event and load the text from saved settings OnLoaded event, after weeks of experimentation I was able to reproduce the issue in an minimal app for you guys to test.
Aim : Ultimately no matter I use dark or light theme to save the RTF text in this rich edit box, whenever it is loaded again in whatever theme it should show the correct text color in both dark and light themes. and during the running app if the user changes theme of their device, the text color should also change as expected. I am not sure how to save the rtf text here it ignores the text color maybe?
Reproduce the bug here : https://github.com/touseefbsb/RichEditBoxColorBug
Make sure your device theme is on "Dark".
Run the app and add some text into the RichEditBox (the textblock and button on top are just to make sure the app doesnt focus automatically on richeditbox when page loads).
click somewhere else on screen to loose focus from richeditbox, then close the app.
Run the app again you you'll notice the text you entered before is already there as expected, now close the app.
Turn the theme of ur device to "Light" and again run the app, now you will notice the richeditbox seems to be empty.
But actually it isnt empty, the issue is the textcolor is white just like the color of richeditbox while the text color shouldve been black in light theme. This can be proved just by selecting the text with cursor and notice the highlighted text appears.
Note
Everytime you change something and try to test the whole flow again just make sure to change the key
string in both Loaded and TextChanged events, to make sure entirely new RTF value is being saved and being loaded later, the key in loaded and textchanging events must always match and should be changed everytime you want to start from step 1.
CODE
Xaml
<StackPanel>
<TextBlock>abc</TextBlock>
<Button>abc</Button>
<RichEditBox
x:Name="REB"
Height="60"
AcceptsReturn="True"
BorderThickness="0"
Loaded="REB_Loaded"
PlaceholderText="placeholder."
TextChanged="REB_TextChanged"
TextWrapping="Wrap" />
</StackPanel>
Code Behind
private void REB_Loaded(object sender, RoutedEventArgs e)
{
var localSettings = ApplicationData.Current.LocalSettings;
var localValue = localSettings.Values["ts5"] as string; // Change the key value on every new test
var text = string.IsNullOrEmpty(localValue) ? string.Empty : localValue;
REB.Document.SetText(TextSetOptions.FormatRtf, text);
}
private void REB_TextChanged(object sender, RoutedEventArgs e)
{
var localSettings = ApplicationData.Current.LocalSettings;
REB.Document.GetText(TextGetOptions.FormatRtf, out var tmpNar);
if (!string.IsNullOrEmpty(tmpNar) && !string.IsNullOrWhiteSpace(tmpNar))
{
localSettings.Values["ts5"] = tmpNar; // Change the key value on every new test
}
}
MISC Info
Windows 10 device version : 1903
Project target and min sdk version : 1903
I had similar issues trying to convert RTF to HTML from a RichEditBox.
Intro
As long as we assume you don't allow font color changes it is not that hard. Both suggested options would also work if you allow font color changes through the document, but this introduces a lot of work and trade-off (i.e. do you invert colors selected in light theme when displaying them in dark?, certain colors look better with black background, others with white, etc.)
1. Change the ITextDocument
This option is quite simple and works quite well. Underneath the RichEditBox there is an ITextDocument which contains the actual text (accessed through RichEditBox.Document). After you set the text of this document you can also set the font color (it is even possible to change to font color for certain parts of the text this way):
REB_Loaded
private void REB_Loaded(object sender, RoutedEventArgs e)
{
var localSettings = ApplicationData.Current.LocalSettings;
var localValue = localSettings.Values["ts4"] as string;
var text = string.IsNullOrEmpty(localValue) ? string.Empty : localValue;
REB.Document.SetText(TextSetOptions.FormatRtf, text);
// Select all text currently in the RichtEditBox
// and make it white or black depending on the currently requested theme
REB.Document.GetRange(0, text.Length).CharacterFormat.ForegroundColor =
Window.Current.Content is FrameworkElement fe
? fe.ActualTheme == ElementTheme.Dark
? Windows.UI.Colors.White
: Windows.UI.Colors.Black
: Windows.UI.Colors.Black; // Assume light theme if actual theme cannot be determined
}
I have tested this and this seems to work as well.
2. Change the RTF
A more low-level method would be to just change the raw RTF just after you load it from the LocalSettings and just before you set the text of the RichEditBox. If you inspect the raw RTF you would see something like this:
{\rtf1\fbidis\ansi\ansicpg1252\deff0\nouicompat\deflang2057{\fonttbl{\f0\fnil\fcharset0 Segoe UI;}{\f1\fnil Segoe UI;}}
{\colortbl ;\red255\green255\blue255;}
{\*\generator Riched20 10.0.19041}\viewkind4\uc1
\pard\tx720\cf1\f0\fs21\lang1033 test text\f1\par}
The thing to note here is the second line: {\colortbl ...}, this part defines the font color. If you now just change the 255's to 0's you change the font from white to black. I have written two extensions methods and a quick test in your code seems to work:
Extension class
public static class Extensions
{
public static string ConvertWhiteTextToBlack(this string s)
=> s.Replace("\\red255\\green255\\blue255", "\\red0\\green0\\blue0");
public static string ConvertBlackTextToWhite(this string s)
=> s.Replace("\\red0\\green0\\blue0", "\\red255\\green255\\blue255");
}
REB_Loaded
private void REB_Loaded(object sender, RoutedEventArgs e)
{
var localSettings = ApplicationData.Current.LocalSettings;
var localValue = localSettings.Values["ts4"] as string;
var text = string.IsNullOrEmpty(localValue) ? string.Empty : localValue;
System.Diagnostics.Debug.WriteLine("[REB_Loaded (start)]" + text);
// Make black text white if dark theme is requested
text = Window.Current.Content is FrameworkElement fe
? fe.ActualTheme == ElementTheme.Light
? text.ConvertWhiteTextToBlack()
: text.ConvertBlackTextToWhite()
: text.ConvertWhiteTextToBlack(); // Assume light theme if actual theme cannot be determined
System.Diagnostics.Debug.WriteLine("[REB_Loaded (end)]" + text);
REB.Document.SetText(TextSetOptions.FormatRtf, text);
}
P.S. I hope these solutions are also applicable outside your MVCE and in your main app. If not post a reply, and I'll try to help you out.
P.P.S. You don't need to change your whole PC theme to change the app from dark to light. Instead just set the RequestedTheme property in the Page header in MainPage.xaml to either Light or Dark.
My problem is that when I paste text into a rich text box I would like to get rid of all the formatting. Now this basically works:
private void RichTextBox1_Pasting(object sender, DataObjectPastingEventArgs e)
{
if (hasImage(Clipboard.GetDataObject()))
{
e.CancelCommand();
}
RichTextBox rtb = sender as RichTextBox;
if (Clipboard.ContainsText(TextDataFormat.Rtf) || Clipboard.ContainsText())
{
// get rid of formatting
string append = Clipboard.GetText(TextDataFormat.UnicodeText);
Clipboard.SetText(append, TextDataFormat.UnicodeText);
}
}
The problem is: If I previously had formatted text in my rich text box (e.g., bold text) and removed this text, the caret would still be bold (or italic if italic was previously selected - this is easy to spot since the caret would be oblique!). In this case, the text would also be inserted with this formatting. How can I get rid of that?
If you want to clear the entire document of previous formatting, you could do something like:
TextRange wholeDocument = new TextRange(Document.ContentStart, Document.ContentEnd);
wholeDocument.ClearAllProperties();
If you want to keep the previous formatting (i.e. you are appending), it looks like this may be useful: https://msdn.microsoft.com/en-us/library/ms597038(v=vs.110).aspx
Although this only solves part of the problem, it is satisfactory for our purposes:
rtb.Selection.ClearAllProperties();
With this line, the formatting of the selected text is removed. So if you mark some text that is formatted and press CTRL+V, the text from the clipboard is inserted without formattings.
What remains unsolved is how to clear the formattings of the caret if you just remove a couple of characters using backspace.
I'm using a 'Paste' button command in my view Model to copy RTF from the clipboard. PastedText is my string property that a RichTextBox is bound to in my view:
private void FormatPastedTextCommandAction()
{
PastedText += Clipboard.GetText(TextDataFormat.Rtf);
}
This works and the text is pasted on pressing the Paste button. However, I want to lock down the formatting on the paste function and remove all formatting from the pasted RTF string (colour, italics, set to black Arial 12).
I would just use PastedText += Clipboard.GetText();
to get the plain text but it pastes in at a different font size and I need it in RTF format. I've looked at iterating over the RTF string and doing a find/replace on font size, colour etc. but the RTF is very complex even for a couple of words.
Is there any way around this? Thanks
In the end I used code behind in the view to strip formatting from the RichTextBox itself using a 'Format' button:
private void _btnFormat_Click(object sender, RoutedEventArgs e)
{
TextRange rangeOfText = new TextRange(richTextBoxArticleBody.Document.ContentStart, richTextBoxArticleBody.Document.ContentEnd);
rangeOfText.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
rangeOfText.ApplyPropertyValue(TextElement.FontSizeProperty, "12");
rangeOfText.ApplyPropertyValue(TextElement.FontFamilyProperty, "Arial");
rangeOfText.ApplyPropertyValue(TextElement.FontStyleProperty, "Normal");
rangeOfText.ApplyPropertyValue(Inline.TextDecorationsProperty, null);
rangeOfText.ApplyPropertyValue(Paragraph.MarginProperty, new Thickness(0));
}
This does a good job and doesn't really break the MVVM pattern as the code is UI logic only.
If I copy some text with different format and paste it to my richtextbox it is not plain I mean its format will be copied as well.
Is there anyway I can copy-paste as a plain text?
By the way my program is on WinForm
thanks for any answer
you must use WinForm RichTextBox (not in UI, just in code), even if you are on WPF, in order to convert RTF to plain text. Use this method in your Copy event.
C# code :
private String ConvertRtfToText()
{
System.Windows.Forms.RichTextBox rtfBox = new System.Windows.Forms.RichTextBox();
rtfBox.Rtf = this.rtfData;
return rtfBox.Text;
}
VB.Net Code :
Private Function ConvertRtfToText() As String
Dim rtfBox As RichTextBox = New RichTextBox()
rtfBox.Rtf = Me.rtfData
Return rtfBox.Text
End Function
source : http://msdn.microsoft.com/en-US/en-en/library/vstudio/cc488002.aspx
I recently had the same issue. I did want to retain some of the formatting, i.e. paragraphs and line feeds, but I required all the addition text format to be removed.
I'm working in WPF but the RichTextBox interface is the same. I have created a button that will allow users to select some text and remove the formatting. It is very simple, you just need to use the ClearAllProperties() method on the TextSelection object.
C# Code (WPF):
private void ClearFormat_Click(object sender, RoutedEventArgs e)
{
rtbText.Selection.ClearAllProperties();
}
This is a super easy solution but perhaps not super elegant...
1) Add a plain textbox to your form and make it hidden
2) Create a button to remove the formatting (or you can do this
automatically when the text is pasted)
3) In the OnClick (or OnPaste) code just copy the text from the rich
textbox control to the plain textbox control then copy the text
from the plain textbox back to the rich textbox control (see example
below)
private void btnRemoveFormatting_Click(object sender, EventArgs e)
{
txtPlainText.Text = txtRTF.Text;
txtRTF.Text = ""; // Required - this makes sure all formatting is gone
txtRTF.Text = txtPlainText.Text;
}