I have a WinForms application, in which I have a label, where I bind a decimal to. I have also added a .Format method to the binding. Like this:
// Add data binding for the lavel
Binding bindWithFormat = new Binding("Text", viewModel, nameof(viewModel.BindingNumber));
bindWithFormat .Format += viewModel.FormatAsNumber;
lblNumber.DataBindings.Add(bindWithFormat);
// Formatting function
public void FormatAsNumber(object sender, ConvertEventArgs e)
{
// The method converts only to string type. Test this using the DesiredType.
if (e.DesiredType != typeof(string)) return;
// Formats the value with thousand separator and zero decimals
e.Value = String.Format("{0:N0}", e.Value);
}
This works fine under normal circumstances, but if I choose a particular type of Digit Grouping Symbol, it looks like this (it is supposed to show "15 000 000"):
I first thought it was when I used a blank space (" ") as symbol, but when I explicitly type a blank space, then it shows it as intended. However, there is another symbol I can chose in the regional settings, which looks like a space, but it causes the above formatting error when selected (unlike when I explicitly type space):
What the heck is going on? According to this website, the symbol is "no break space" (U+00A0). So it is a space. But not a space. And for some reason, it seriously messes up the formatting. What to do?
Bonus info: After playing around some more, it seems to only affect that specific font, that I was using (it only exists in my company). If I change fonts to e.g. Segoe UI, then the problem disappears.
Related
when I using confidence the punctuation is not working just like I am saying question mark it was typing question mark instant ? and when I say period it was typing period instant . I have make a checkbox when you click on the checkbox the punctuation will be on
SpeechConfig config = SpeechConfig.FromSubscription("key", "region");
config.OutputFormat = OutputFormat.Detailed;
if (Properties.Settings.Default.Punctuation)
{
config.SetServiceProperty("punctuation", "explicit", ServicePropertyChannel.UriQueryParameter);
}
recognizer = new SpeechRecognizer(config);
recognizer. Recognizer. Recognizedecognizer_Recognized;
...
private void SpeechRecognizer_Recognized(object sender, SpeechRecognitionEventArgs e)
{
if (e.Result.Reason == ResultReason.RecognizedSpeech)
{
if (e.Result.Text.ToLower().Equals("new line") || e.Result.Text.ToLower().Equals("newline"))
{
SendKeys.SendWait(Environment.NewLine);
}
else
{
var detailedResults = e.Result.Best();
if (detailedResults != null && detailedResults.Any())
{
var bestResults = detailedResults?.ToList()[0];
foreach (var word in bestResults.Words)
{
double per = word.Confidence * 100;
SendKeys.SendWait($"{word.Word} [{per:0.##}] ");
}
}
}
}
}
What you are observing is by design. In most circumstances it not necessary or even helpful to inspect the details of recognized speech result. It looks like you have misinterpreted how to use the details.
You don't realise it but your example of detecting "new line" or "newline" as a key phrase and interpreting that as a request to inject a line feed into the output is the very same process at work.
For puntuation to be detected in the speech, the first thing that the classifier must do is resolve the words. It is only after the word has been resolved that the service can post process the results to classify the word as a natural word or punctuation.
The process is a bit like this:
Detected the word "comma" with high confidence
If the punctuation setting is set to explicit, then Is the word on its own or at the end of a recognized sequence that was followed by a pause
If yes, then interpret it as "," and not "comma"
For this reason it is important to understand that when the punctuation setting is set to explicit, the punctuation must be isolated out of the normal sentence cadence of the spoken text.
Read this as a sentence with a constant pace without punctuation:
this is a sentence that doesn't have a comma or a full stop but an exclamation mark would look nice
If you read fast and fluent enough, there should be no punctation in the output, even if the words were recognized with high confidence. To get punctuation into the same text, you actually need to read this script:
This is a sentence that doesn't have a comma.
Comma.
Or a fullstop.
Comma.
But an exclamation mark would look nice.
exclamation mark.
This is a sentence that doesn't have a comma , or a full stop , but an exclamation mark would look nice !
The per-word analysis for my test looks like this:
word
confidence
this
85.99%
is
95.93%
a
68.49%
sentence
96.99%
that
90.03%
doesn't
96.75%
have
94.57%
a
87.88%
comma
94.58%
comma
94.34%
or
67.14%
a
64.68%
fullstop
77.63%
comma
94.90%
but
91.17%
an
62.65%
exclamation
98.44%
mark
68.58%
would
86.15%
look
91.58%
nice
97.40%
exclamation
97.05%
mark
96.61%
Notice that the words representing the punctuation all have a high confidence rating, but in the output not all of the words were actually interpreted as punctuation. This might be clearer in this screenshot where I have highlighted two commas that are in the output, but are correctly identified as words:
In this screenshot, the panel on the left is populated with e.Result.Text and the panel on the right with the Word and Confidence.
DetailedSpeechRecognitionResult.Words
Returns the Word level timing result list.
The Words list is designed to be used to map the recognised word back to a specific offset and duration in the audio file that was submitted for analysis. You would use this information when testing and training the model or if you wanted to display the text as sub-titles for an audio or video clip. Punctuation is not shown at this level, it is purely about timing only, all it has done is literally transcribed the spoken audio into English vocabulary. It is the responsibility of other analytical functions to use this information to determine which detected words might represent punctuation or to determine context or sentiment.
FWIW this is my Recognized event handler:
recognizer.Recognized += (s, e) =>
{
// Checks result.
if (e.Result.Reason == ResultReason.RecognizedSpeech)
{
Console.WriteLine($"RECOGNIZED: Text={e.Result.Text}");
string text = e.Result.Text;
if (e.Result.Text.ToLower().Equals("new line") || e.Result.Text.ToLower().Equals("newline"))
text = Environment.NewLine;
// update the left textbox
this.BeginInvoke(SetText, textBox1, text);
var detailedResults = e.Result.Best();
if (detailedResults != null && detailedResults.Any())
{
var bestResults = detailedResults?.ToList()[0];
foreach (var word in bestResults.Words)
{
double perc = word.Confidence * 100;
// update the right textbox
this.BeginInvoke(SetText, textBox2, $"{word.Word} [{word.Confidence:p2}] " + Environment.NewLine);
}
}
}
else if (e.Result.Reason == ResultReason.NoMatch)
{
Console.WriteLine($"NOMATCH: Speech could not be recognized.");
}
};
...
delegate void SetTextDelegate(TextBox textBox, string text);
private SetTextDelegate SetText = delegate (TextBox textbox, string text)
{
textbox. Text += " " + text;
};
Using cognitive services I cannot reproduce your issue. Setting the config.OutputFormat = OutputFormat.Detailed or config.RequestWordLevelTimestamps(); does not affect the explicit punctuation recognition.
What is not clear from your example is the current state of your setting. When in doubt, if we are toggling logic using settings, and the behaviour that we observe is the same even when we change the setting values then the obvious code to check is the setting value itself.
Please try to comment out your logic to toggle the punctuation like this:
//if (Properties.Settings.Default.Punctuation)
{
config.SetServiceProperty("punctuation", "explicit", ServicePropertyChannel.UriQueryParameter);
}
If this solves it then there are two considerations:
What is the initial state of the Properties.Settings.Default.Punctuation setting? Is your application logic not updating the value when you expect it to? Any mutating logic that affects that setting may need to call Properties.Settings.Default.Save() to save changes. An extension of this of course is that depending on where your mutating logic is executing from, you might need to call Properties.Settings.Default.Reload() to ensure that the current values are loaded from the store, however this is not usually required if you are operating in the same thread space, which you most likely will be in WinForms.
Is the config loaded once, and is that once before the setting value has been toggled? That step in the workflow is unclear from your description and the code example. If you are using continuous recognition or you are creating a single instances of SpeechRecognizer for the lifetime of your Form then changes to your setting will not be applied into the Speech Configuration.
You will need to re-initialize the SpeechRecognizer as part of your logic that is handling the setting changed event or have some other routine in the speech event handlers that detects a change in this setting and restarts the SpeechRecognizer connection and process.
I noticed that when the mask defined for input in a MaskedTextBox contains "/", it is automatically substituted by "-" in the textbox.
I tried this using the default Date format available in VS, which in the form's Designer results in the following code
this.maskedTextBox2.Name = "maskedTextBox2";
this.maskedTextBox2.Mask = "00/00/0000";
this.maskedTextBox2.ValidatingType = typeof(System.DateTime);
and also for another MaskedTextBox by defining my custom mask in the form's constructor like this
InitializeComponent();
this.maskedTextBox1.Mask = #"00/00/0000";
In both cases the prompt displayed in the text boxes looks like this
__-__-____
Is there a way to actually display slashes there, instead of dashes?
Marek
According to this page, a slash is a 'date separator' and therefore I'm guessing that your system currently runs in a locale where a date separator is a dash.
/ Date separator. The actual display character used will be the date symbol appropriate to the format provider, as determined by the control's FormatProvider property.
If you really DO want a forward slash then "00\/00\/00" should do the trick (but then it's not really a compliant date input).
With the following code, I delete line by line in a TextBox (0, 39). Now there is on the last place a money amount (1 any Articel 10.00) which I want to deduct from the total amount. For that, I use the Substring. But there I get errors, as probably the empty spaces are not interpreted. Is there a simple solution to this? Thanks
private void btnDelete_Click(object sender, EventArgs e)
{
if (TextBox1.Text.Length > 0)
{
txtTotal.Text = (Double.Parse(txtTotal.Text) - Double.Parse(TextBox1.Text.Substring(8, 2))).ToString("0.00");
TextBox1.Text = TextBox1.Text.Remove(0, 39);
}
if (TextBox1.Text.Length == 0)
{
MessageBox.Show("The cart is empty");
Few things you can do to make your life easier (assuming you have to keep a TextBox as you have stated to others.)
Before I get into the details however, the issue seems to be you're having trouble parsing text that represents lines of data, data which contains amounts which you want to act on. If this is an incorrect assumption, disregard this answer.
Ok, back to it...
Rather than trying to work with the text directly in the TextBox, start by reading in your entire string as a list of lines (i.e. List<String>). You can do that with the Split function or with RegEx expressions. See here
Use RegEx expressions for each line to identify not just the type of line it is (an 'item' line or the 'All' line at the bottom) as well as the various parts of those lines. For instance, you can use a RegEx that starts at the end of the line and goes backwards looking for a number (in the form of a string.) Use the result of that for your Parse method to get the actual numeric value.
Finally, if you still need to remove the lines of text (I'm not sure if you're removing the text just for your logic or if you need to display it) simply remove them from your list of strings for the lines. If it needs to be displayed back in the UI (doubtful as it seems it should be blank at the end of processing) just use Join to convert the lines back to a string, then set that back to the TextBox.Text property.
Hope this helps!
Mark
P.S. To (try and) avoid comments such as the ones you got about your design, it may help to start your question by saying something like 'Unfortunately I'm restricted to using a TextBox due to issues outside of this question, hence I'm looking for an answer here.' At least that should cut back on those responses telling you to 'Do it differently!' instead of answering your question.
I am trying to align values. I wonder why this happen :
string value = "";
value += string.Format("{0,-10}", "value");
value += string.Format("{0,5}", "value");
value += Environment.NewLine;
value += string.Format("{0,-8}", "val");
value += string.Format("{0,7}", "value");
Print(value);
If i check value before i "Print" it is correct. The result is:
value value
val value
As they should be, but when i print "value" to my printer then they get like this :
value value
val value
I really cant understand why it changes the string when i print the text?
I have tried to use "\t" but my printer dont seem to understand "\t" because the tabs isnt printed out.
Btw: this is just a test code so you could understand the problem that i am having with the real code.
your console uses fixed width fonts where your printer does not (at least by default). So spaces take up less space on your printer and your letters take up more or less space based on their actual width.
This could be caused by a font that uses different character widths. In non-fixed-width fonts, spaces are often narrower than letters and numbers, so it might seem that spaces are missing. Consider using Lucida Console or another fixed-width font.
I am trying to align values.
I wonder why this happen :
string value = "";
value += string.Format("{0,-10}", "value");
value += string.Format("{0,5}", "value");
value += Environment.NewLine;
value += string.Format("{0,-8}", "val");
value += string.Format("{0,7}", "value");
MessageBox.Show(value);
If i check value before i do "MessageBox.Show() it is correct. The result is:
value value
val value
As they should be, but when i do MessageBox.show() then they get like this :
value value
val value
I really cant understand why it changes the string with show()? Same thing happens when i am trying to print "value", then it doesnt align correct.
Btw: this is just a test code so you could understand the problem that i am having with the real code.
This might be caused by the fact that the font used in the message box is not monospaced, meaning that each character takes an equal amount of horizontal space. The font you are using in the Visual Studio debugger probably is, which is why the padding looks entirely different.
You could try if using tabs instead of spaces for your formatting gives better results.
That's because the font used by MessageBox.Show doesn't have a fixed width...
According to this answer the way to go is using \t as a column seperator.
This definitely involves checking the length of all the words of each single column. This way you would know whether to use a single \t or double \t\t etc.