How do you stop the Winforms timer firing Tick event?
this is my code:
Timer tm = new Timer();
private void button1_Click(object sender, EventArgs e)
{
tm = new Timer();
tm.Interval = 1000;
tm.Tick += new EventHandler(tm_Tick);
tm.Start();
}
void tm_Tick(object sender, EventArgs e)
{
MessageBox.Show("hi");
tm.Stop();
}
I am unsure of what you are trying to do. Are you trying to make the tick event handler only execute once? If that is the case, your current setup will only stop the timer from firing tick events when the first message box is closed. To avoid this problem, switch the two lines in your tm_Tick method.
Also, you shouldn't set up the Timer in the click handler. You should only start it. I suggest you to do something in the lines of this:
Timer tm;
private void form1_Load(object sender, EventArgs e)
{
tm = new Timer();
tm.Interval = 1000;
tm.Tick += new EventHandler(tm_Tick);
}
private void button1_Click(object sender, EventArgs e)
{
tm.Start();
}
void tm_Tick(object sender, EventArgs e)
{
tm.Stop();
MessageBox.Show("hi");
}
Related
I have a BackgroundWorker on my WPF UserControl.
private readonly BackgroundWorker worker = new BackgroundWorker();
public ucCustomer()
{
InitializeComponent();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
// run all background tasks here
System.Threading.Thread.Sleep(10000);
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//update ui once worker complete his work
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
worker.RunWorkerAsync();
}
Above code is work, the UI is response when the task is working, but if i change the worker_DoWork() to
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
// run all background tasks here
Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background,
new Action(() => {
gridDataBind(); //A long data-mining task,using Dispatcher.Invoke() to access UI.
}));
}
private void gridDataBind()
{
SnEntities sn = new SnEntities();
var customers = from c in sn.Customer select c;
dgCustomer.ItemsSource = customers.ToList();
}
The UI is freeze until the task is end.
Is it any solution?
Thanks you.
Try setting the ItemsSource like below code:
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
// run all background tasks here
e.Result = gridDataBind(); //A long data-mining task.
}
private IList<Customer> gridDataBind()
{
SnEntities sn = new SnEntities();
var customers = from c in sn.Customer select c;
return customers.ToList();
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
var customers = e.Result as IList<Customer>;
ObservableCollection<Customer> gridItemsSource = new ObservableCollection<Customer>();
Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background,
new Action(() =>
{
dgCustomer.ItemsSource = gridItemsSource;
}));
foreach(var customer in customers)
{
Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background,
new Action(() =>
{
gridItemsSource.Add(customer);
}));
}
}
Store your data in e.result at worker_DoWork and update UI at the worker_RunWorkerCompleted.
in that case UI will be free when data will coming from database.
Try this, it should help you
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => gridDataBind();));
I am developing an analog clock picker control.
The user is able to click on the minute or hour hand and drag to turn the needle to select the specific time. I was wondering how to detect such a click and drag event.
I tried using MouseLeftButtonDown + MouseMove but I cannot get it to work as MouseMove is always trigger when the mousemove happen despite me using a flag. Is there any easier way?
public bool dragAction = false;
private void minuteHand_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
dragAction = true;
minuteHand_MouseMove(this.minuteHand, e);
}
private void minuteHand_MouseMove(object sender, MouseEventArgs e)
{
if (dragAction == true)
{
//my code: moving the needle
}
}
private void minuteHand_MouseLeftButtonUp(object sender, MouseEventArgs e)
{
dragAction = false;
}
I think this is the easiest and most straightforward way :
private void Window_MouseMove(object sender, MouseEventArgs e) {
if (e.LeftButton == MouseButtonState.Pressed) {
this.DragMove();
}
}
public bool dragAction = false;
private void minuteHand_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
dragAction = true;
minuteHand_MouseMove(this.minuteHand, e);
}
private void minuteHand_MouseMove(object sender, MouseEventArgs e)
{
if (dragAction == true)
{
this.DragMove();
}
}
private void minuteHand_MouseLeftButtonUp(object sender, MouseEventArgs e)
{
dragAction = false;
}
does the trick
You can make things easier and need not handle mouse down / up :
private void minuteHand_MouseMove(object sender, MouseEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
//my code: moving the needle
}
}
It is possible to detect a touch press and hold gesture with the MouseRightButtonDown event. Unfortunately it fires not until I release my finger from the screen. This is to late!
Does anyone have ideas? Thanks in advance.
It is possible to do that in an awaitable fashion. Create a timer with specific interval. Start it when user tapped and return the method when timer elapsed. If user release the hand, return the method with false flag.
public static Task<bool> TouchHold(this FrameworkElement element, TimeSpan duration)
{
DispatcherTimer timer = new DispatcherTimer();
TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
timer.Interval = duration;
MouseButtonEventHandler touchUpHandler = delegate
{
timer.Stop();
if (task.Task.Status == TaskStatus.Running)
{
task.SetResult(false);
}
};
element.PreviewMouseUp += touchUpHandler;
timer.Tick += delegate
{
element.PreviewMouseUp -= touchUpHandler;
timer.Stop();
task.SetResult(true);
};
timer.Start();
return task.Task;
}
For more information, read this post.
Great piece of code. I add just an example usage for completeness:
private async void btn_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (await TouchHold(btn, TimeSpan.FromSeconds(2)))
{
// todo: long press code goes here
}
}
And from XAML:
<Button Name="btn" PreviewMouseDown="btn_PreviewMouseDown">Press long</Button>
Use the Hold gesture provided by Blake.NUI toolkit
Either a button or label or image, we can use the MouseDown and MouseUp for starting the delay and Stopping the delay.
For MouseDown,
// Declaration of timer and timercount
int timerCount = 0;
DispatcherTimer dt = new DispatcherTimer();
public myConstructor()
{
dt.Interval = new TimeSpan(0, 0, 1);
}
// Mouse Down Event
private void EnterHoldState(object sender, TouchEventArgs e)
{
timerStarted();
}
//Mouse Up event
private void ExitHoldState(object sender, RoutedEventArgs e)
{
timerStopped();
}
// Stops the timer and resets the timer count to 0
private void timerStopped()
{
dt.Stop();
timerCount = 0;
}
// Starts the timer and sets delayCounter function for counting the delay seconds and acts on it
private void timerStarted()
{
dt.Tick += delayCounter;
dt.Start();
}
//Once delay timer reaches 2 seconds, the button navigates to nextpage.
private void delayCounter(object sender, EventArgs e)
{
timerCount++;
if (timerCount == 2)
{
this.NavigationService.Navigate(new nextPage());
}
}
I recently had to implement a Button where I needed to it to trigger after being pressed for five seconds.
To do this I created an attached behavior. I have the five seconds backed into the behavior as I did not need this configurable but easily done with a Dependency Property and it is hooked up to be used with a Command in an MVVM way but it could easily be changed to trigger Click.
<Button Command="{Binding Path=ButtonCommand}">
<i:Interaction.Behaviors>
<behaviors:PressAndHoldBehavior />
</i:Interaction.Behaviors>
</Button>
public sealed class PressAndHoldBehavior : Behavior<Button>
{
private DispatcherTimer dispatcherTimer;
protected override void OnAttached()
{
dispatcherTimer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(5)};
dispatcherTimer.Tick += OnDispatcherTimerTick;
AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObjectPreviewMouseLeftButtonDown;
AssociatedObject.PreviewMouseLeftButtonUp += AssociatedObjectPreviewMouseLeftButtonUp;
}
protected override void OnDetaching()
{
dispatcherTimer.Stop();
dispatcherTimer.Tick -= OnDispatcherTimerTick;
dispatcherTimer = null;
AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObjectPreviewMouseLeftButtonDown;
AssociatedObject.PreviewMouseLeftButtonUp -= AssociatedObjectPreviewMouseLeftButtonUp;
}
private void AssociatedObjectPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
dispatcherTimer.Start();
e.Handled = true;
}
private void AssociatedObjectPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
dispatcherTimer.Stop();
e.Handled = true;
}
private void OnDispatcherTimerTick(object sender, EventArgs e)
{
AssociatedObject.Command.Execute(null);
}
}
For a textbox, I want to display a tooltip immediatly when the focus is in on the textbox, and stay there for the duration of the focus - not just when the mouse hovers over the textbox.
How can I do that?
The Enter and Leave events are probably useful here, and show it with a duration of 0 to keep it there.
private ToolTip tt;
private void textBox1_Enter(object sender, EventArgs e) {
tt = new ToolTip();
tt.InitialDelay = 0;
tt.IsBalloon = true;
tt.Show(string.Empty, textBox1);
tt.Show("I need help", textBox1, 0);
}
private void textBox1_Leave(object sender, EventArgs e) {
tt.Dispose();
}
Note: Calling the Show(...) method twice like in my example will force the "pointer" to point correctly to the control.
have tested, the event names:
private void textbox_Enter(object sender, EventArgs e)
{
toolTip1.Show("your tip here", textbox);
}
private void textbox_Leave(object sender, EventArgs e)
{
toolTip1.Hide(textbox);
}
tooltip is a control, needs to be added from toolbox.
using mouse hover and mouse leave events
private void textBox1_MouseHover(object sender, EventArgs e)
{
toolTip1.Show("your tip here", textBox2);
}
private void textBox1_MouseLeave(object sender, EventArgs e)
{
toolTip1.Hide(textBox2);
}
>
Windows Forms
public partial class FormWindow : Form
{
//Constructor
public FormWindow()
{
txtUrl.Text = "Enter text here";
txtUrl.ForeColor = Color.Gray;
txtUrl.GotFocus += TxtUrl_GotFocus;
txtUrl.LostFocus += TxtUrl_LostFocus;
}
private void TxtUrl_GotFocus(object sender, EventArgs e)
{
txtUrl.Text = "";
txtUrl.ForeColor = Color.Black;
}
private void TxtUrl_LostFocus(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txtUrl.Text))
{
txtUrl.Text = "Enter text here";
txtUrl.ForeColor = Color.Gray;
}
}
}
Use a System.Windows.Forms.ToolTip and show it in textbox GotFocus event and Hide it in LostFocus event:
void textBox_GotFocus(object sender, EventArgs e)
{
toolTip.Show("your tip", textBox);
}
void textBox_LostFocus(object sender, EventArgs e)
{
toolTip.Hide(textBox);
}
I am building a proof of concept application before it gets rollout to the real one.
Scenario
I should be able to stop processing in the middle of it.
Toolbar 2 buttons "Start" & "Stop"
User press start and it process a long running task.
User decides out of the blue to stop the task.
I cannot seem to get threading right!! I cannot press stop as it's waiting for the long running task as if the long running task is actually running on UI thread and not as intented on background thread.
What Am I doing wrong can you spot it? Thanks for your help
public partial class TestView : UserControl
{
private readonly BackgroundWorker _worker;
public TestView
{
InitializeComponent();
_worker = new BackgroundWorker();
_worker.RunWorkerCompleted += RunWorkerCompleted;
_worker.DoWork+=DoWork;
_worker.WorkerReportsProgress = true;
_worker.ProgressChanged+=_worker_ProgressChanged;
_worker.WorkerSupportsCancellation = true;
}
static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("The task has been cancelled");
}
else if (e.Error != null)
{
MessageBox.Show("Error. Details: " + e.Error);
}
else
{
MessageBox.Show("The task has been completed. Results: " + e.Result);
}
}
private delegate void SimpleDelegate();
void DoWork(object sender, DoWorkEventArgs e)
{
for (var i = 0; i < 1000000; i++)
{
_worker.ReportProgress(i, DateTime.Now);
// SimpleDelegate simpleDelegate = () => txtResult.AppendText("Test" + System.Environment.NewLine);
//Dispatcher.BeginInvoke(DispatcherPriority.Normal, simpleDelegate);
}
MessageBox.Show("I have done it all");
}
private void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
DateTime time = Convert.ToDateTime(e.UserState);
txtResult.AppendText(time.ToLongTimeString());
txtResult.AppendText(Environment.NewLine);
}
private void BtnStart_Click(object sender, RoutedEventArgs e)
{
_worker.RunWorkerAsync();
}
private void BtnStop_Click(object sender, RoutedEventArgs e)
{
_worker.CancelAsync();
MessageBox.Show("Process has been stopped!");
}
}
You run a very tight loop inside of DoWork and continuously push Invoked ProgressUpdates to the Main Thread. That will make it sluggish.
But the real problem is that DoWork has to cooperate in Cancellation:
void DoWork(object sender, DoWorkEventArgs e)
{
for (var i = 0; i < 1000000; i++)
{
if (_worker.CancelationPending)
{
e.Cancel = true;
break; // or: return to skip the messagebox
}
_worker.ReportProgress(i, DateTime.Now);
}
MessageBox.Show("I have done it all"); // remove or make depend on Cancelled
}