C# - How to Italicise a words within a string resource [duplicate] - c#

This question already has an answer here:
Concatenate StaticResources in WPF
(1 answer)
Closed 5 years ago.
I'm writing a WPF application and I need to italicise words within descriptions on my view while still having them within resources to provide multi-lingual support later on. These descriptions are resourced and pass through a director that matches the descriptions in the view model by their code to their appropriate placement.
What I have tried:
I've begun resourcing the words of importance separately and added placeholder codes within the description resources. I then wanted to insert the words of importance into the description strings as they pass through the director but I can't italicise them at this stage either as they're just strings! How can i do achieve this?

This is typically a case where you are intertwining your data with the view of your data. You should keep them separated, as Model-View-Controller (MVC) advises.
You have some data that consists of two parts:
your description
the texts within your description that needs to be emphasized
This data can be displayed on several ways. One way - the method you want - is to display the complete description while the texts that need to be emphasized must be shown in italics.
But one could also think of a viewing method where the emphasized words are shown in bold fond, or a different font, or in red, or upside down.
By separating your data from the way you view your data, it is possible to change this view without having to change the data itself
Now back to your question. So you have some text, and some subtext that need to be emphasized. How you know which text needs to be emphasized is out of scope of your question. How you put this information inside this class is also out-of-scope of this question. All you need is some translate function that will translate your text into a format that allows interpreters of the translated text to know the complete text, and which phrases must be emphasized.
How to mark where the emphasize starts and where it stops is not really important, just use some well-defined method.
For instance, you could use the HTML method for emphasis:
Some normal text <em>is emphasized</em> and normal again
If you want, you could use any other method, like adding double forward slashes to switch emphasizing on or off, or anything else. It doesn't matter, as long as it is well defined.
So the class that holds your text and your emphasized needs a procedure to extract the translated text
public string ExtractTranslatedText()
{
// TODO: take your original text and add <em> and </em>
// to mark begin and end of emphasis
}
It seems that you almost succeeded creating this function.
Now once you've got a string that holds this emphases, you need to display it. It depends on your display class how this can be done.
Suppose you want to display it italicized in a RichTextBox. You could derive your class from RichTextBox, or you could create an extension function for RichTextBox.
See Extension Methods Demystified
public static class RichTestBoxExtensions
{
// TODO: add the required functions
}
We need a function that will append some text to the already existing text in the text box in a given System.Drawing.FontStyle:
public static void AppendText(this RichTextBox box, string text, FontStyle fontStyle)
{
box.SelectionStart = box.TextLength;
box.SelectionLength = 0;
Font savedSelectionFont = box.SelectionFont;
box.SelectionFont = new Font(box.SelectionFont, fontStyle);
box.AppendText(text);
box.SelectionFont = savedSelectionFont;
}
If you want, you could also add methods to show the text in a different color.
The code will be very similar.
Now you need to put your translated string with emphasis markers in the rich text box
public static ShowEmphasis(this RichTextBox, string text, FontStyle emphasisStyle)
{
const string emphasisOn = "<em>";
const string emphasisOff = "</em>";
while(!String.IsNullOrEmpty(text))
{ // still some text to print
// get the substring until first emphasisOn
int indexStartEmphasis = text.Index(emphasisOn);
if (indexStartEmphasis == -1)
{ // no emphasisOn anymore: write all in emphasisStyle
richTextBox.AppendText(text, emphasisStyle);
text = String.Empty; // no text left
}
else
{ // write until emphasisOn:
string normalText = text.SubString(0, indexStartEmphasis);
richTextBox.AppendText(normalText, FontStyle.Normal);
// remove the normalText + <em> from text:
text = text.Substring(indexStartEmphasis + emphasisOn.Length);
// do the same until emphasisOff
int indexStopEmphasis = text.Index(emphasisOff);
if (indexStopEmphasis == -1)
{ // no emphasisOff anymore: write all in emphasisStyle
richTextBox.AppendText(text, FontStyle.Normal);
text = String.Empty; // no text left
}
else
{ // write until emphasisOff in emphasisStyle:
string emphasizedText = text.SubString(0, indexStopEmphasis);
richTextBox.AppendText(emphasizedText, emphasisStyle);
// remove the emphasizedlText + </em> from text:
text = text.Substring(indexStopEmphasis + emphasisOff.Length);
}
}
}
}

If your resources will be consumed by a TextBlock you have to separate the text into separate inlines.
E.g.:
The text you want to show is This is an italic, bold and underlinded text.
This string need to be split up into separate parts for your resource file like the following:
Res1: This is an
Res2: italic
Res3: ,
Res4: bold
Res5: and
Res6: underlined
Res7: text
Your XAML then should look like the following:
<TextBlock FontSize="14">
<Run Text="{x:Static p:Resources.Res1}" />
<Run Text="{x:Static p:Resources.Res2}" FontStyle="Italic" />
<Run Text="{x:Static p:Resources.Res3}" />
<Run Text="{x:Static p:Resources.Res4}" FontWeight="Bold" />
<Run Text="{x:Static p:Resources.Res5}" />
<Run Text="{x:Static p:Resources.Res6}" TextDecorations="Underline" />
<Run Text="{x:Static p:Resources.Res7}" />
</TextBlock>
This results in the following format:

If you have an entire description as one string presented in f.e. a label, and you only want one part of this string italic, then this is not possible.
In case of a label (not sure what control is presenting your descriptions) you can create a seperated label for this important word, and place this specific label (with the italic property set) where you want it to be.

Related

C# Winforms RichTextBox. How to limit number of characters by size of rtb?

How to limit number of characters by size of rtb? The same question for WPF textbox.
I tried to limit it by compare clientSize of rtb with Graphics.MeasureString and TextRenderer.MeasureText, but their both have some mistake in calculations, and TR.MeasureText cannot wrap one long word as rtb. So I have a big problem with long words.
In WPF I used FormattedText to get text size, but it also doesn't wrap long words.
About the logic: in paste command I tried to make Adobe Acrobat logics for text fields: when you paste long text in middle of other text, you paste only that number of chars which you can.
Sorry for my language.
For WPF simply use the "MaxLength" property of TextBox.
Pasting a text limits it to the set amount of characters, but keep in mind that a newline (CR LF - 2 characters) is also counted. If you paste it in middle of text- the pasted content will be limited to how many characters are left until MaxLength.
Since OP mentioned this is about the width, not length, this is the path to consider - trimming the text based on the wrapping mechanism of WPF with a TextBox that has a set MaxWidth.
private void this_TextChanged(object sender, TextChangedEventArgs e)
{
if (sender is TextBox)
{
var textb = sender as TextBox;
if (textb.LineCount > 1)
{
foreach (var change in e.Changes.Where(x=>x.RemovedLength == 0))
{
for (int index = change.AddedLength; index > 0; index--)
{
textb.Text = textb.Text.Remove(change.Offset, 1);
textb.UpdateLayout();
if (textb.LineCount == 1)
break;
}
if (textb.LineCount == 1)
break;
}
}
}
}
And the .xaml for such TextBox
<TextBox TextChanged="this_TextChanged" MaxWidth="200" Text="{Binding TextValue}" TextWrapping="Wrap"/>
This is only a rough example - trimming a pasted text works fine, however it doesn't work if you select a part of already existing text and try to replace it by pasting text - the problem comes from updating the Text within TextChanged, which fires it once more - pasting in such way without the:
e.Changes.Where(x=>x.RemovedLength == 0)
causes the text in front of TextBox to be trimmed instead - probably fixable.

How do I display "Android backspace" - ⌫ in Label

I have a Xamarin application with a Label which is Bound like so:
<Label Text="{Binding BackSpace}"/>
and a property in my viewmodel like so:
public string BackSpace
{
get
{
ResourceManager temp = new ResourceManager("MyProgram.ResourceStrings", typeof(MyClass).GetTypeInfo().Assembly);
result = System.Text.RegularExpressions.Regex.Unescape(temp.GetString("Backspace"));
}
}
now I have an element in my ResourceStrings called Backspace and I am trying to get the string associated with this key which I want to be the Android Backspace - ⌫
So initially I set the resource equal to the symbol ⌫ but this just gives me a label containing ?
Now I try set it equal to the HTML hex code from here: ⌫ but this gives me ⌫
How do I get my label to display the ⌫ symbol?
PS. - Even if I try:
<Label Text="⌫"/>
I get a blank label
You'll need to change your label's font to a font which contains backspace as glyphicon.
You'll need two things:
Appropriate font. Probably Noto Sans Symbols https://www.google.com/get/noto/#sans-zsym. ⌫ symbol
Label renderer which allows custom fonts. See here: https://github.com/XLabs/Xamarin-Forms-Labs/wiki/ExtendedLabel
This Xamarin link will provide more infomation on working with Fonts

Android Webview equivalent in Windows Phone 8 app

I have text with some HTML tags in it.
Example : <I> I Play Football and Cricket </I>
Now when i try to display this text in Textblock it displays with Italics tag <I> as well.
The data is present in the XML file and i am working on Windows Phone 8 application.
In Android we use Webview, but what do i need to use here ?
EDIT
I have tried using TextBlock with inlines:
Italic itlText = new Italic();
itlText.Inlines.Add(new Run() { Text = "This is some example text in italics" });
Inilinetext.Inlines.Add(itlText);
It works good But issue here is suppose i have a text like below.
"This is text in <I>Italics</I> here"
Now it display entire text in italics.
This depends on how much content you want to display. If you will show large amount of HTML text, use WebBrowser control for that.
In case you only have a couple of tags i, em, b or strong, then you can actually use TextBlock, but you would have to do the parsing yourself then in order to convert the HTML to the suitable XAML components.
You also have to ask yourself how many such controls you need to display on a single page. If the answer is a few, use the WebBrowser then. If you need to display lots of them, say you have a chat or a feed, then the second route would be better.
EDIT:
Use the following code:
Inilinetext.Inlines.Add(new Run() { Text = "This is text in " });
Inilinetext.Inlines.Add(new Run() { Text = "Italics", FontStyle = FontStyle.Italic });
Inilinetext.Inlines.Add(new Run() { Text = " here" });
I told you you have to parse the original string to see which parts are italic and which are not.

Printing a flowdocument with dynamic data in WPF

I am trying to find a good way to print a flow document in WPF. What I want is to have a possibility to see how the document turns out as I design it, so therefore creating a pure FlowDocument as a XAML is out of the questions (as Visual Studio wont show the design view for it).
So what I have done now is to create a window that contains a FlowDocument like this (some excessive parts have been removed to make the code more consise):
<Window x:Class="MyNamespace.ProjectPrintout...>
<Grid>
<FlowDocumentReader>
<FlowDocument ColumnWidth="500" Name="Document">
<!-- Header -->
<Paragraph Name="HeaderText">
The header will go here
</Paragraph>
</FlowDocument>
</FlowDocumentReader>
</Grid>
</Window>
This is a bit strange since I will never show this Window to the user, and I only wrap the FlowDocument with a Window so that I can see how it looks like as I develop it. This Ican live with.
So somewhere else in my application, I want to print this FlowDocument to the default printer, but I also have to set the header dynamically (in addition to many other parts of the documents that needs dynamic data that are omitted here).
The code to print looks like this:
var printout = new ProjectPrintout();
printout.HeaderText= new Paragraph(new Run("Proper header text"));
var document = printout.Document;
var pd = new PrintDialog();
IDocumentPaginatorSource dps = document;
pd.PrintDocument(dps.DocumentPaginator, "Document");
The document is getting printed, and looks fine except that the header text still shows "The header will go here", even if I replaced it from my code with "Proper header text". I also tried changing it like this:
(printout.HeaderText.Inlines.FirstInline as Run).Text = "Proper header text";
But the result is the same.
So the question is: How can I change the contents in the FlowDocument from code before I print it, or are there a better way to do this instead of my approach?
MVVM to the rescue:
Epiphany: UI is not Data. UI is not a data store. UI is meant to show Data, not to store it.
1 - Create a simple object to hold your data
public class MyDocumentViewModel: INotifyPropertyChanged //Or whatever viewmodel base class
{
private string _header;
public string Header
{
get { return _header; }
set
{
_header = value;
NotifyPropertyChange(() => Header);
}
}
//Whatever other data you need
}
2 - Define Bindings in your Document;
<Paragraph>
<Run Text="{Binding Header}"/>
</Paragraph>
3 - Set your FlowDocument's DataContext to an instance of this class:
var flowdoc = new YourFlowDocument();
var data = new MyDocumentViewModel { Header = "this is the Header" };
//whatever other data
flowdoc.DataContext = data;
//do the printing stuff.

How to find the font-name,size,style, text color from rich text-box text in c#

In my application I have a rich text-box.I use that as a text editor. I can change font,size, style when I needed. now my problem is I want to find out font-name,size, text-color of each character ?
i,e i want to retrieve every character's font-name,size, text-color after editing is done.
You can use the SelectionFont property to retrieve the font of the currently selected text. Similarly, you can use the SelectionColor property.
Never done this personally and no time to test at the moment, but the: Groups RV's DotNET forum may have your solution. Perhaps something like mentioned in the post:
for (int iCurChar = lastChar; iCurChar
richTextBox1.Text.Length; iCurChar++)
{
richTextBox1.Select(iCurChar,1);
char CurrChar = richTextBox1.Text[iCurChar];
Color CurrColor = richTextBox1.SelectionColor;
Font CurrFont = richTextBox1.SelectionFont;
float fontSize = CurrFont.Size
}
Taking a look at the Font class may be useful as well: Microsoft's Font Reference Page

Categories