I have created a class which generates a random number:
public class DataGenerator
{
public void RandomHRValue()
{
Random random = new Random();
int RandomNumber = random.Next(0, 100);
}
}
I have then created a XAML file and put the following within the Grid:
<TextBlock Name="a" Text="" Width="196" HorizontalAlignment="Center" Margin="183,158,138,56"/>
I haven't done anything to the xaml.cs file. How would I go about putting a random number into that TextBlock every 20 seconds?
You can use DispatcherTimer like this:
public MainWindow()
{
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 20);
timer.Start();
timer.Tick += timer_Tick;
}
void timer_Tick(object sender, EventArgs e)
{
DataGenerator dg = new DataGenerator();
a.Text = dg.RandomHRValue().ToString();
}
Also change method type to int:
public int RandomHRValue()
{
Random random = new Random();
int RandomNumber = random.Next(0, 100);
return RandomNumber;
}
I can't comment due to my low reputation, but in response to the other answer, would it not be better to use the following?
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer {Interval = new TimeSpan(0, 0, 5)};
timer.Start();
timer.Tick += timer_Tick;
If this is wrong, can you say why, so I, myself, can get some feedback (btw OP and I are working together on this)
Related
I have this code
Color[] colours = new Color[5]{Color.Red, Color.Blue, Color.Green, Color.Yellow, Color.Black};
public int randGen(int lower, int upper)
{
Random random = new Random();
return random.Next(lower, upper);
}
public PlayGame()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
changeColour();
}
public void changeColour()
{
int milliseconds = randGen(1000, 5000);
int count = 0;
Device.StartTimer(TimeSpan.FromMilliseconds(milliseconds), () =>
{
var layout = new StackLayout { Padding = new Thickness(5, 10) };
var label = new Label { Text = "Time: ", TextColor = Color.Green, FontSize = 25 };
layout.Children.Add(label);
label.Text += milliseconds.ToString();
this.Content = layout;
if (count < 4)
{
BackgroundColor = colours[count];
count++;
milliseconds = randGen(1000, 5000);
return true;
}
else
{
BackgroundColor = Color.Black;
return false;
}
}
);
}
Which has an array of colours. The idea is that every 1-5 seconds (which should be random each time), the background colour should change, and the text should write how long the screen was on for.
Currently, however, the time shown in the text is not reflective of the time each screen shows for, and I have some speculative concern that milliseconds in:
Device.StartTimer(TimeSpan.FromMilliseconds(milliseconds)
doesn't change at all. Any ideas?
this is what I would do - have your timer fire every second (or whatever granularity you need) but only execute your code every X times
using System.Timers;
// these are class variables
Timer timer;
int timecount = 0;
// adjust this dynamically so your code only executes every 1-n seconds
int interval = 1;
// to this wherever you want to start the timer
timer = new Timer();
timer.Elapsed += Timer_Elapsed;
// fire every 1 sec
timer.Interval = 1000;
timer.Start();
// timer event handler
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
timecount++;
if (timecount == interval)
{
timecount = 0;
// do other stuff here
}
}
I have been trying to run a very simple application that moves a 20 by 20 pixel square 20 pixels to the right on a canvas every second. I am using a dispatchertimer to fire the event every second.
The problem is that the square doesn't move to the right unless I shake the application window (with my mouse), and it occasionally moves on its own (albeit not every second).
I have already tried reinstalling Visual Studio 2017 and installing it on my SSD and HDD, neither seem to fix the issue.
Here is the full code of the application's MainWindow.xaml.cs
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
DispatcherTimer timer = new DispatcherTimer();
Rectangle s = new Rectangle();
Point currentPosition = new Point(20, 20);
public MainWindow()
{
InitializeComponent();
timer.Tick += Timer_Tick;
timer.Interval = TimeSpan.FromSeconds(1);
timer.Start();
s.Width = 20;
s.Height = 20;
s.Fill = new SolidColorBrush(Colors.Black);
map.Children.Add(s);
}
public void Timer_Tick(object sender, EventArgs e)
{
RedrawSquare();
}
public void RedrawSquare()
{
map.Children.Clear();
s.Width = 20;
s.Height = 20;
s.Fill = new SolidColorBrush(Colors.Black);
Canvas.SetLeft(s, currentPosition.X += 20);
map.Children.Add(s);
}
}
On the MainWindow.xaml file there is an empty Canvas with the name "map"
Thank you in advance
You don't need to remove and add the Rectangle on each timer tick, or reset its properties each time.
Just increment the value of the Canvas.Left property:
public partial class MainWindow : Window
{
private readonly DispatcherTimer timer = new DispatcherTimer();
private readonly Rectangle s = new Rectangle();
public MainWindow()
{
InitializeComponent();
timer.Tick += Timer_Tick;
timer.Interval = TimeSpan.FromSeconds(1);
timer.Start();
s.Width = 20;
s.Height = 20;
s.Fill = Brushes.Black;
Canvas.SetLeft(s, 0);
map.Children.Add(s);
}
public void Timer_Tick(object sender, EventArgs e)
{
Canvas.SetLeft(s, Canvas.GetLeft(s) + 20);
}
}
The movement would however be much smoother with an animation:
public MainWindow()
{
InitializeComponent();
s.Width = 20;
s.Height = 20;
s.Fill = Brushes.Black;
Canvas.SetLeft(s, 0);
map.Children.Add(s);
var animation = new DoubleAnimation
{
By = 20,
Duration = TimeSpan.FromSeconds(1),
IsCumulative = true,
RepeatBehavior = RepeatBehavior.Forever
};
s.BeginAnimation(Canvas.LeftProperty, animation);
}
You can try setting the DispatcherPriority to Normal.
Instantiate your timer like this:
DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Normal);
EDIT:
Although this somehow fixed the issue (square was moving without the need to move the window), it's apparently still the wrong answer. I don't know much about the DispatcherTimer, but I recall having changed the priority once but I don't remember why. In any case, it might be helpful to someone else.
I want to move a rectangle in WPF application using the following code. However, I am getting the following error:
System.InvalidOperationException: Cannot use a DependencyObject that belongs to a different thread
I looked at other problems in stackoverflow but nothing worked.
public partial class MainWindow : Window
{
private Rectangle rect;
int count = 1;
Timer timer;
public MainWindow()
{
InitializeComponent();
Rectangle movedRectangle = new Rectangle();
movedRectangle.Width = 200;
movedRectangle.Height = 50;
movedRectangle.Fill = Brushes.Blue;
movedRectangle.Opacity = 0.5;
TranslateTransform translateTransform1 = new TranslateTransform(50, 20);
movedRectangle.RenderTransform = translateTransform1;
this.can.Children.Add(movedRectangle);
this.rect = movedRectangle;
timer = new Timer(500);
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}
private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
count++;
TranslateTransform translateTransform1 = new TranslateTransform(50 + count * 2, 20);
this.rect.Dispatcher.Invoke(new Action(()=>
rect.RenderTransform = translateTransform1));
//this.can.UpdateLayout();
this.can.Dispatcher.Invoke(new Action(()=>
this.can.UpdateLayout()
));
}
I would suggest you to use DispatcherTimer than a normal timer.
Please see the below solution. enjoy.
Note: for DispatcherTimer you will need to add the assembly reference for System.Windows.Threading
public partial class MainWindow : Window
{
private Rectangle rect;
int count = 1;
private DispatcherTimer timer = null;
public MainWindow()
{
InitializeComponent();
Rectangle movedRectangle = new Rectangle();
movedRectangle.Width = 200;
movedRectangle.Height = 50;
movedRectangle.Fill = Brushes.Blue;
movedRectangle.Opacity = 0.5;
TranslateTransform translateTransform1 = new TranslateTransform(50, 20);
movedRectangle.RenderTransform = translateTransform1;
this.can.Children.Add(movedRectangle);
this.rect = movedRectangle;
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
timer.Tick += timer_Tick;
timer.Start();
timer.IsEnabled = true;
}
void timer_Tick(object sender, EventArgs e)
{
count++;
TranslateTransform translateTransform1 = new TranslateTransform(50 + count * 2, 20);
Dispatcher.BeginInvoke(new Action<TranslateTransform>(delegate(TranslateTransform t1)
{
rect.RenderTransform = t1;
this.can.UpdateLayout();
}), System.Windows.Threading.DispatcherPriority.Render, translateTransform1);
}
}
You are constructing a TranslateTransform (which is a DependencyObject) outside the UI thread. Easy fix:
this.rect.Dispatcher.Invoke(new Action(
() =>
{
TranslateTransform translateTransform1 = new TranslateTransform(50 + count * 2, 20);
rect.RenderTransform = translateTransform1;
}));
Arguably a better fix: use a DispatcherTimer instead and get rid of all your Dispatcher.Invoke calls.
I am having problems with making a Timer App on Windows phone.
I have the text box set to 00:00:00 and im trying to increment it every second but after the first second it wont do any more. I am sure it is an easy fix and would be very appreciative of any help. Thank you
public MainPage()
{
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += OnTimerTick;
timer.Start();
}
void OnTimerTick(object sender, EventArgs args)
{
txtTimer.Text = DateTime.Now.ToString();
}
private void btnStartClick(object sender, EventArgs e)
{
DispatcherTimer timer = new DispatcherTimer();
timer.Tick +=
delegate(object s, EventArgs args)
{
TimeSpan time = new TimeSpan(0);
time += TimeSpan.FromSeconds(1);
this.timenow.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);
};
timer.Interval = new TimeSpan(0, 0, 1);
timer.Start();
}
TimeSpan time = new TimeSpan(0);
time += TimeSpan.FromSeconds(1);
this.timenow.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);
The time variable is created each time the timer ticks. Thus each time you add one second to zero time span. You need to extract it from the delegate. Normally you would make it a class field.
Hi I have a ObservableCollection getting data in every minute. When it reaches an hour, I would like to clear the first item and move all the items up then adding the new item, thus maintaining it at 60 elements. Does anyone have any idea how to do so?
Here is my code:
public class MainWindow : Window
{
double i = 0;
double SolarCellPower = 0;
DispatcherTimer timer = new DispatcherTimer();
ObservableCollection<KeyValuePair<double, double>> Power = new ObservableCollection<KeyValuePair<double, double>>();
public MainWindow()
{
InitializeComponent();
timer.Interval = new TimeSpan(0, 0, 1); // per 5 seconds, you could change it
timer.Tick += new EventHandler(timer_Tick);
timer.IsEnabled = true;
}
void timer_Tick(object sender, EventArgs e)
{
SolarCellPower = double.Parse(textBox18.Text);
Power.Add(new KeyValuePair<double, double>(i, SolarCellPower ));
i += 5;
Solar.ItemsSource = Power;
}
}
Just count the items in your list and remove the top item if the count equals 60. Then insert the new item like normal.
if (Power.Count == 60)
Power.RemoveAt(0);
Power.Add(new KeyValuePair<double, double>(i, SolarCellPower ));
Also if you Bind your ItemsSource instead of setting it, it will update automatically when the collection changes.