Really really odd problem, in short, I'm doing a foreach over every word in a textblock, if that word starts with for example "#" I want to make a username hyperlink out of it. However in about 70% of the cases it replaces the text fine, but it just doesn't become a hyperlink.
Partial code:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
var kaas = Tweet.Split(' ');
foreach (string a in kaas)
{
if (a.StartsWith("#"))
{
Hyperlink uname = new Hyperlink();
uname.NavigateUri = new Uri("http://twitter.com/" + "xarinatan");
uname.RequestNavigate += new RequestNavigateEventHandler(Hyperlink_RequestNavigateEvent);
uname.Inlines.Add("ASDAS");
TweetBlock.Inlines.Add(uname);
//TweetBlock.Inlines.Add(Username(a));
TweetBlock.Inlines.Add(" ");
}
}
}
Above code turns all instances that start with "#" into "ASDAS" but fails most of the time to properly convert it to a hyperlink, HOWEVER it DOES convert it SOMETIMES.
It's completely beyond me how it only works sometimes, instead of all the time or not at all.
All suggestions are welcome!
edit: To clarify, it -always- replaces the text with 'ASDAS', but in 70% of the cases it doesn't become a hyperlink.
My friend found the answer. Somehow inlines being added as string causes sporadic behavior, they have to be added as a 'Run'.
Fix can be found here: https://github.com/zahndy/o3o/commit/68b50f8c0ea106bcc709d3f69658b28da9c8a9d4#diff-3
Thanks all for the suggestions!
Related
I am making this sum creator where user will have to type an answer using custom keyboard. and on check button click if answer is correct then new question is loaded.
My problem is after answering first question answer button reset to blank but when user types next answer, only one last alphabet is deleted (for example 5 from 15). and when i type 14 it shows 114 (1 from previously typed answer).
I need help to reset answer button text to blank.
I am using buttons because later i want to add more questions at the same time so user will have multiple answers to click and type.
Can anyone please help me on this? Also tell me if this is the right method to achieve what i want.
I am calling backspace function to delete previous answer and also setting text to blank.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Keyboard : MonoBehaviour
{
string word = null;
int wordIndex = -1;
string alpha = null;
string alpha2 = null;
public Text userAnswer1 = null;
public Text valueA, valueB;
public Text scoreCount;
private int a, b, answer1, score;
char[] nameChar = new char[5];
private void Start()
{
SumCreator();
}
public void nameFunc (string alphabet)
{
wordIndex++;
char[] keepchar = alphabet.ToCharArray();
nameChar[wordIndex] = keepchar[0];
alpha = nameChar[wordIndex].ToString();
word = word + alpha;
userAnswer1.text = word;
}
public void BackspaceFunction()
{
if (wordIndex >= 0)
{
wordIndex--;
alpha2 = null;
for (int i = 0; i < wordIndex + 1; i++)
{
alpha2 = alpha2 + nameChar[i].ToString();
}
word = alpha2;
userAnswer1.text = word;
}
}
public void SumCreator ()
{
a = Random.Range(0,15);
b = Random.Range(0,15);
answer1 = a + b;
valueA.text = a.ToString();
valueB.text = b.ToString();
scoreCount.text = "score " + score.ToString();
}
public void CheckAnswer()
{
Text buttonText = userAnswer1.GetComponentInChildren<Text>();
if (answer1 == int.Parse(userAnswer1.text))
{
score++;
// userAnswer1.text = string.Empty;
buttonText.text = string.Empty;
}
SumCreator();
}
}
I've edited my answer and removed the now irrelevant parts.
Once the button "Check" is clicked, first of all erase the text in the result textbox, then do the whole other logic.
To erase the text you can use next piece of code:
Text buttonText = buttonName.GetComponentInChildren<Text>();
buttonText.text = string.Empty;
You probably want to have this "buttonText" property as a global and get it once, at the start of the program instead of getting it every time the button is clicked. It won't do much difference in a small scale program, but it's a right way of thinking.
After checking your code a bit more, I can summarize your problem:
The whole logic of your program is flawed, there're many unnecessary complicated things which make it fail in several places. It is understandable, everybody goes through this stage, nothing to be ashamed or worried about. Either way it's my subjective opinion, which may be wrong.
Back to your code, all you have to do is update your result text, say "txtResult", once anything happens.
Once you click a number, do "txtResult += numberClicked".
Once you click backspace, remove last char of txtResult. Here is a question with many answers on how to do it, it's really simple.
Once you click "Check", in case it's the right number, set txtResult to empty.
Also, every time you update txtResult, you're supposed to update the UI too of course. Let's say you do it every time, it would be one line to update txtResult, and one line to update UI for each of the above 3 cases. So in total 6 lines. A check for an empty string while in "Backspace" function adds another line. My math could be wrong, but either way, it's quite short and simple approach, nothing too complicated.
You just lack relevant knowledge, otherwise you wouldn't be doing that nightmare in your Backspace function.
Regarding the "nameFunc" function, the whole 6 lines could be replaced with "txtResult += alphabet", isn't it? I'm not sure what you get in alphabet parameter, but either way, string is an array of chars, so you can also do "txtResult += alphabet[0]" instead of what you have there.
So, in total, you got it all right, the logic was right, you figured the main aspects. But you over complicated the whole thing. I believe you'll be fine after reading all this text, and wish you the best.
If you want to clear your Text object when you have succesfully entered your answer, you should not call your "BackSpace" function.
Just replace your code to this:
if (answer1 == int.Parse(userAnswer1.text))
{
score++;
userAnswer1.text = string.Empty;
This will clear the text element.
You could also look into using InputFields in Unity, which are designed for entering input and automatically support backspace and other keyboard functions.
If you do, make sure that you set the InputField's ContentType to either Integer Number or Decimal Number
I'm new to C# and trying to understand how things work. So I created a two forms. First one has a textbox and the second one has a combobox with a button that sends offer help to that computer. From the text box I add computer names. once I click the OK button it loads all my computer names to the combobox.
string[] computerlist = txtComputers.Text.Split(new[]{'\n'}, StringSplitOptions.RemoveEmptyEntries);
frmHome _frmhome = new frmHome();
_frmhome.cbComputerList.Items.AddRange(computerlist);
_frmhome.ShowDialog();
_frmhome.Dispose();
When I select a computer from the dropbox and click Offer_help button, offer remote window comes up saying its trying to connect to the user but then fails.
private void Offerhelp_Click(object sender, EventArgs e)
{
CompName = cbComputerList.SelectedItem.ToString();
var _offerhelp = new ProcessStartInfo();
_offerhelp.FileName = "msra.exe";
_offerhelp.Arguments = String.Format("/offerRA" + " " + CompName);
Process.Start(_offerhelp);
}
I tried running in debug mode and I see that "CompName" variable is
"/offerRA Lab1\r"
if I remove the "\r" it actually works.
Can anyone tell me why this is happening? Also, Is there a way I can create a new class for the selected item and make it a global variable so I can use it say if I create 4-5 forms and use that computer name in all forms?
Thanks in advance.
Your line
string[] computerlist = txtComputers.Text.Split(new[]{'\n'}, StringSplitOptions.RemoveEmptyEntries);
Is the issue. \n is the newline operator, and \r is carriage return. Depending on OS / Program, you can use \r\n to determine a 'NewLine'.
Use
string[] computerlist = txtComputers.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
Environment.NewLine will return the proper character.
EDIT: In terms of your comment, add a static property to your form:
class MyForm
{
public static string SelectedComputer { get; set;}
}
you can then reference this anywhere by
MyForm.SelectedComputer
Set this variable on your cbComputerList.SelectedIndexChanged event. Just check to make sure the value is greater than 0 then set it.
Hi I am writing some code for my homework and I am stuck. I created one general click event handler for digit Buttons:
private void btnN_Click(object sender, EventArgs e),
and now I need to make frequency Array which I need to update every time when one of the button is clicked.
Here is freqArray:
private int[] freqArray = new int[10];
How can I do that if there is let say nine buttons?
Thank you
lastNum is number of buttons.
private void btnN_Click(object sender, EventArgs e)
{
for (int i = 0; i < lastNum; i++)
{
freqArray[i]++;
lstFrequencies.Items[i] = i + "\t\t" + freqArray[i];
}
}
Gosh, this is getting out of hand.. but since the original idea of giving hints and helping you along the way has hit the wall - I'll discuss the problem and will leave the decision to you..
The core problem is to identify within the common click event just which of the many buttons has been clicked. The key to this is usually in the event's parameters; in this case the sender is the button that got clicked.
We will look at three different ways to identify the sender:
By comparing it to the Control
By looking at its Name
By using an index stored in its Tag
So the simplest and most direct approach would be something like this:
if (sender == button1) freqArray[0]++;
else if (sender == button2) freqArray[1]++;
..
Note that while the designer names the controls you add with a count from 1 the programmers count from 0! (As do many data structures in C# including your array of counts!)
There are other approaches and since we are doing a little lesson here we go:
Sender is of the most basic type object; you can cast an object to its actual Type like this:
Button b = (Button) sender;
And now you can access all the button's properties, including the Name. So you could write the above code like this:
if (b.Name == "button1") freqArray[0]++;
else if (b.Name == "button2") freqArray[1]++;
..
This has un-coupled the actual button control from the identification and replaced it by a string.
And there is a general purpose property called Tag, which incidentally is also of class object; you can store anything in it. This makes it sometimes quite valuable and often one creates a special structure or even class just to store many things in a Tag..
So if you have created the Buttons to have their Tag contain an index you could use that:
freqArray[ (int) ( (Button) sender).Tag) ]++;
Note the double casts and all those parenthesis! It looks complicated and it is. It is just one line instead of the long vector of if clauses we saw before. But it only works if you have set the Tags before, maybe in the load event:
button1.Tag = 0;
button2.Tag = 1;
button3.Tag = 2;
...
So you have to invest first and can harvest later..
A lot to digest here.. Your pick!
One thing you must understand is you shouldn't ask for approach to a problem. However since your question requires it.
First you should add Tags to the buttons to differentiate them:
button1.Tag = "1";
button2.Tag = "2";
.
.
.
Then in your event handler cast the sender object to your control type:
Button a = (button)sender;
Then check the tag of the button a to add frequencies:
freqArray[Convert.ToString(a.Tag)-48] = freqArray[Convert.ToString(a.Tag)-48] + 1;
Hi I am using HtmlAgilityPack to scrap some data from web using c# . Here is the code :
private void button1_Click(object sender, EventArgs e)
{
var url = this.textBox1.Text;
var webGet = new HtmlWeb();
var document = webGet.Load(url);
var metaTags = document.DocumentNode.SelectNodes("//meta");
if (metaTags != null)
{
foreach (var tag in metaTags)
{
var name = tag.Attributes["name"].Value;
var content = tag.Attributes["content"].Value;
this.textBox2.Text = name + " : " + content;
}
}
}
its getting a link from textbox1 and showing the output to textbox2 . Its showing the last available data . I can concate the available data but it will show all data at once. Actually I want to show one data when it is available while others are being processed so that user can realize the scrapping progress.Would anyone please help ??
Assuming the first half of your code is correct, this will show the data one-by-one. Most likely, the foreach loop is executing too quickly for you to notice the "one-by-one" effect.
You could apply an artificial delay if you need to display each result long enough for someone to read. Maybe with a Timer or something similar.
An alternative is to use a multi-line textbox (for example a RichTextBox) and place each result on a new-line. Or a ComboBox, which won't take up as much room. These options allow you to keep the data, without having to overwrite it.
You can user Timer control to delay the display of next value in the loop.
You can also use BackgroundWorker to get this done. However this would add complexity to your code. Please look at Beginners Guide to Threading in .NET: Part 5
Or you can use Thread.Sleep(xx) which will delay the execution for the milliseconds you specify.
Thread.Sleep(2000);
this.textBox2.Text += name + " : " + content + Environment.NewLine;
I suppose there's a limit for the lines alowed in a TextBox with the MultiLine option set to true.
I have a program that every several minutes, checks an email account, but for control purposes i put a TextBox that indicates what's been doing.
My curiosity is, does anyone know how much lines are allowed ? And does throw an exception when reached that line ?
EDIT Sorry forgot to mention is in WinForms
EDIT 2 Perhaps, someone knows of a way to eliminate older lines, will grated appreciated
There's no limit on the number of lines that a text box can display.
There is, however, a limit on the number of characters that the control can hold. See this question for further details on this topic.
If you set the TextBox.MaxLength property to zero, the amount of text is limited only by available memory.
Another solution:
<TextBox x:Name="txtAddress"
MaxLines="6"
TextWrapping="Wrap" AcceptsReturn="True"
VerticalScrollBarVisibility="Hidden"
HorizontalScrollBarVisibility="Hidden"
TextChanged="txtAddress_TextChanged"
PreviewTextInput="txtAddress_PreviewTextInput"
PreviewKeyDown="txtAddress_PreviewTextInput"/>
//...
private void txtAddress_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox txtBx = sender as TextBox;
if (txtBx.LineCount > txtBx.MaxLines)
txtAddress.Text = this._textBeforInput;
}
private string _textBeforInput = string.Empty;
private void txtAddress_PreviewTextInput(object sender, EventArgs e)
{
this._textBeforInput = txtAddress.Text;
}
There is no such limitation on Multiline TextBox both in WinForms and ASP.NET. (I have no idea of WPF :) )
I know this question is really old and has already been answered, but for those searching for an HTML/ASP.NET solution I have created a short jsFiddle http://jsfiddle.net/Z3rdZ/2/
HTML
<textarea id="limited-lines" maxlines="4"></textarea>
jQuery
$('#limited-lines').keydown(function(event){
if ( event.which == 13 ) {
var numberOfLines = $(this).val().split('\n').length;
if(numberOfLines >= $(this).attr('maxlines')){
event.preventDefault();
}
}
});