When event handler updates the content of a control? C#,WPF - c#

I have this silly C# code on a buttonClick (WPF) handler and i wonder why the text box shows only the last value(=0) and no the previous values(9-1) . When I tested the code to a console application I saw all values in the command line.(I am beginner to C#,WPF)
Thnx
private void clock_Click(object sender, RoutedEventArgs e)
{
DateTime clicktime = DateTime.Now;
int nextsecont = DateTime.Now.Second + 1;
int now = clicktime.Second;
int timer = 10;
do
{
if (nextsecont == DateTime.Now.Second)
{
now++;
timer--;
nextsecont++;
textbox3.Text = timer.ToString();
}
} while (nextsecont <= (clicktime.Second + 10));
}
PS: I know there are better ways to do that (f.e. to use timer) but this is not the point.
Sorry for my english..
Explanation: now i see the initial value for 10 seconds and then i see the 0. I don't see intermediate values..

If you want all of the data to display in the textbox, you'll need to append the data to what is already in there.
textbox3.Text += " " + timer.ToString();
That will take what is in there, add a space, and then the timer.

Related

How to update a UI element multiple times while in an event handler?

I have an event handler on a button that runs some lines of code. All the code does is run bubble sort on a list but also does some changes to some rectangles on a canvas. My problem is those changes only appear once it has exited the event handler. A similar question has been asked before however that only does one change instead of multiple in concession UI update in WPF elements event handlers.
This is a similar goal to what I'm trying to achieve.
If you're interested in what exactly the code is:
private void Run_btt_Click(object sender, RoutedEventArgs e)
{
Key hold = new Key();
var converter = new System.Windows.Media.BrushConverter();
double hold2, hold3;
//for inside a for loop(bubble sort)
for (int i = 0; i < Sequence.Count; i++)
{
for (int c = 0; c < Sequence.Count-i-1; c++)
{
//changes the colour of the 2 that are being compared
Sequence[c].shape.Fill =(Brush)converter.ConvertFromString("#FFFF00");
Sequence[c+1].shape.Fill = (Brush)converter.ConvertFromString("#FFFF00");
//pause for a bit so that you can see what the algorithm is doing
Thread.Sleep(delay);
if (Sequence[c].Value > Sequence[c + 1].Value)
{
// swap the 2 rectangles
hold2 = Canvas.GetLeft(Sequence[c].shape);
hold3 = Canvas.GetLeft(Sequence[c + 1].shape);
hold = Sequence[c];
Sequence[c] = Sequence[c + 1];
Sequence[c + 1] = hold;
Canvas.SetLeft(Sequence[c].shape, hold2);
Canvas.SetLeft(Sequence[c + 1].shape, hold3);
}
//set colour back to normal
Sequence[c].shape.Fill = (Brush)converter.ConvertFromString(Sequence[c].Colour);
Sequence[c + 1].shape.Fill = (Brush)converter.ConvertFromString(Sequence[c + 1].Colour);
}
}
}
I'm sorry if this question is too vague or not enough detail but I don't know much about this topic and really just starting out.
Just putting #Clemens comment as answer.
If you give the method the async like:
public void async methodname()
and then once you need to update the UI you add:
await Task.Delay(1);
This will act like break point in your code that will update the UI with the changes you made. The 1 represents how long in millisecond the delay will be.

C# String comparison not working

I'm having this wierd problem within the application I'm currently working on.
string searchText = "onMouseOver=\"CallList_onMouseOver(this);\" id=\"";
List<int> searchOrders = AllIndexesOf(scraper.clientBrowser.DocumentText, searchText);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < searchOrders.Count; i++)
{
string order = scraper.clientBrowser.DocumentText.Substring(searchOrders[i] + searchText.Length, 6);
scraper.clientBrowser.Document.GetElementById(order).InvokeMember("Click");
for (int j = 0; j < scraper.clientBrowser.Document.Window.Frames.Count; j++)
{
if (scraper.clientBrowser.Document.Window.Frames[j].Document != null && scraper.clientBrowser.Document.Window.Frames[j].Document.Body != null)
{
string orderText = scraper.clientBrowser.Document.Window.Frames[j].Document.Body.InnerText ?? "Nope";
//MessageBox.Show(j + Environment.NewLine + orderText);
if (!orderText.Contains("Nope"))
{
sb.AppendLine(orderText + Environment.NewLine);
}
}
}
}
Clipboard.SetText(sb.ToString());
The thing is, whenever I uncomment the MessageBox.Show, I can clearly see orderText is filled with another value than "Nope", the Stringbuilder gets filled, and the correct text is copied.
However if I comment the Messagebox.Show, the outcome of this loop is always "Nope". I'm stuck here, I have no idea what could cause something like this.
The scraper.clientBrowser is a System.Windows.Forms.WebBrowser.
Update:
Solved the issue by waiting for the document to be loaded, created this mechanism:
public bool DocumentLoaded
{
get { return documentLoaded; }
set { documentLoaded = value; }
}
private void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
this.DocumentLoaded = true;
this.clientBrowser = sender as WebBrowser;
}
void clientBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
this.DocumentLoaded = false;
}
Then in the class I'm using:
while(!scraper.DocumentLoaded)
{
System.Threading.Thread.Sleep(100);
}
It sounds like you need to ensure that the page is fully loaded, like there might be a race condition. I would suggest wiring up the WebBrowser.DocumentCompleted event, and then attempting your scrapping logic.
Update
I overlooked this initially, this certainly has something to do with your issue. The line where you are invoking a click, like so scraper.clientBrowser.Document.GetElementById(order).InvokeMember("Click");. This is done in the iteration, which will more than likely manipulate the DOM -- will it not? I suggest going about this problem entirely different. What are you trying to achieve exactly, (not how you're trying to do it)?
With this alone, I would suggest that you refer to this SO Q/A and look at how they're waiting for the click to finish.
Only one thing I can guest here:
When you uncomment MessageBox.Show, at the time the message box show the info, the clientBrowser use this time to finish loading page. Then when you press OK on message box, the page is load completed, so you get the result. When you comment it, you dont wai for page loaded, so the result is diffent.

autoscroll a textbox in c# 1 line down every x seconds

im trying to get a textbox to autoscroll a line down every X seconds.
i have found the AutoScrollOffset and ScrollToCaret functions, but these functions do not give the desired result.
I think my solution would be to do the autoscroll function in a backgroundworkerthread, that does a scroll down by 1 line every x seconds. But i have no idea how to, and info from the net isnt verry usefull either.
I hope someone can help me, thnx in advance!
(im using .net 4.5)
Borrowing heavily from this answer, and combining it with a Timer, you could do something like this:
private int lineNumber = 1;
private void timer1_Tick(object sender, EventArgs e)
{
nfobox.HideSelection = false;
nfobox.SelectionStart = nfobox.GetFirstCharIndexFromLine(lineNumber - 1);
nfobox.SelectionLength = nfobox.Lines[lineNumber - 1].Length;
nfobox.ScrollToCaret();
lineNumber++;
// include some code to detect the last line, or you'll get an exception
}
This will only work if your lines are separated by a line feed.
If it's one long line that wraps, then the whole thing will be selected on the first "tick" and then it's done.
"Grant Winney" is rigth. you can't directly modify the Uİ from a background thread.
But You use the way below.
int lineCounter = 0;
int nextLineLength = 0;
private void timer1_Tick(object sender, EventArgs e)
{
textBox1.SelectionStart = nextLineLength;
textBox1.SelectionLength = 0;
textBox1.ScrollToCaret();
nextLineLength += textBox1.Lines[lineCounter++].Length + "\r\n".Length; //"\r\n" is next line parameters
}

How to prevent StackOverflow error when changing values of two dependent DateTimePickers?

I have the three DateTimePicker, where one of them is the interval between startdate and enddate. In a part of the code, I update startdate.Value and enddate.Value, whose ValueChanged events update interval.Value.
Everything works fine when the value in interval doesn't need to be changed manually. But when I need to change it manually, it causes a StackOverflow exception, because when final.Value is set, it causes interval's ValueChanged event to trigger, which changes final.Value, and so on.
This the ValueChanged handler for startdate and enddate:
private void dates_ValueChanged(object sender, EventArgs e)
{
if (startdate.Value < enddate.Value)
{
TimeSpan diff = enddate.Value - startdate.Value;
DateTime newInterval = new DateTime(startdate.Value.Year, startdate.Value.Month, startdate.Value.Day, diff.Hours, diff.Minutes, diff.Seconds);
if (interval.Value != newInterval)
interval.Value = newInterval;
}
}
And this is the ValueChanged handler for interval, which causes the StackOverflow exception:
private void interval_ValueChanged(object sender, EventArgs e)
{
int seconds = intervaloDP.Value.Hour * 3600 + intervaloDP.Value.Minute * 60 + intervaloDP.Value.Second;
finalDP.Value = finalDP.Value.AddSeconds(seconds);
}
Is there a way to change this code and make it work the way I need it to work?
Make sure that there is always an exit condition:
var dtm = startDP.Value.AddSeconds(seconds);
if (dtm != finalDP.Value)
finalDP.Value = dtm;
This way, the event won't fire if there is no change to make.
UPDATE: Changed code so that seconds are added to startDP, not finalDP.
Actually, you are already doing the right thing by updating the interval only when needed:
if (interval.Value != newInterval) interval.Value = newInterval;
That should be enough to avoid the infinite loop of updates. But you are computing wrongly the other update:
private void interval_ValueChanged(object sender, EventArgs e)
{
int seconds = intervaloDP.Value.Hour * 3600 + intervaloDP.Value.Minute * 60 + intervaloDP.Value.Second;
// finalDP.Value = finalDP.Value.AddSeconds(seconds); //wrong
finalDP.Value = startDP.Value.AddSeconds(seconds);
}
(BTW, you should define your desired behaviour when the interval crosses the 24:00:00 point)

How to display updated time as system time on a label using c#?

I want to display current time on a label using C# but time will continuously change as system time changes. How can I do this?
Add a new Timer control to your form, called Timer1, set interval to 1000 (ms), then double click on the Timer control to edit the code-behind for Timer1_Tick and add this code:
this.label1.Text = DateTime.Now.ToString();
You can Add a timer control and specify it for 1000 millisecond interval
private void timer1_Tick(object sender, EventArgs e)
{
lblTime.Text = DateTime.Now.ToString("dd-MMM-yyyy hh:mm:ss tt");
}
Add a Timer control that is set to fire once every second (1000 ms). In that timer's Tick event, you can update your label with the current time.
You can get the current time using something like DateTime.Now.
Try the following code:
private void timer1_Tick(object sender, EventArgs e)
{
lblTime.Text = DateTime.Now.ToString("hh:mm:ss");
}
You must set the timer to be enabled also, either in code, or in the properties window.
in code, please type the following in the form load section:
myTimer.Enabled = true;
myTimer.Interval = 1000;
After that, make sure your timer event is similar to this:
private void myTimer_Tick(object sender, EventArgs e)
{
timeLabel.Text = DateTime.Now.ToString("hh:mm:ss");
}
Since the timer interval is not exact your update could be in bad sync and will be drifting with respect to the actual seconds transition. At some events you will lag behind or before the transition and miss updates in your time display
Instead of polling att high frequency to fire the update at the change of the seconds this method may grant you some respect.
If you like regulators you can adjust your time update to be safely located 100 ms after the actual second transition by adjusting the 1000 ms timer using the Millisecond property of the timestamp you want to display.
In the timer event code do something like this:
//Read time
DateTime time = DateTime.Now;
//Get current ms offset from prefered readout position
int diffms = time.Millisecond-100;
//Set a new timer interval with half the error applied
timer.Interval = 1000 - diffms/2;
//Update your time output here..
Next timer interval should then trigger closer to the selected point 100 ms after the seconds transition. When at the Transition+100ms the error will toggle +/- keeping your readout position in time.
private int hr, min, sec;
public Form2()
{
InitializeComponent();
hr = DateTime.UtcNow.Hour;
min = DateTime.UtcNow.Minute;
sec = DateTime.UtcNow.Second;
}
//Time_tick click
private void timer1_Tick(object sender, EventArgs e)
{
hr = DateTime.UtcNow.Hour;
hr = hr + 5;
min = DateTime.UtcNow.Minute;
sec = DateTime.UtcNow.Second;
if (hr > 12)
hr -= 12;
if (sec % 2 == 0)
{
label1.Text = +hr + ":" + min + ":" + sec;
}
else
{
label1.Text = hr + ":" + min + ":" + sec;
}
}

Categories