Hold down mouse event in WPF - c#

I'm trying to hold down mouse event using PreviewMouseDown and DispatcherTimer as following:
private void button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
_sec = _sec + 1;
if (_sec == 3)
{
dispatcherTimer.Stop();
MessageBox.Show(_sec.ToString());
_sec = 0;
return;
}
}
This code works, BUT the first mouse down takes 3 seconds to display the message, after that the time to show the message is decreased (less that 3 seconds)

You don't need a DispatcherTimer to do this. You could handle the PreviewMouseDown and the PreviewMouseUp events.
Please refer to the following sample code.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
PreviewMouseDown += Window3_PreviewMouseDown;
PreviewMouseUp += Window3_PreviewMouseUp;
}
DateTime mouseDown;
private void Window3_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
mouseDown = DateTime.Now;
}
readonly TimeSpan interval = TimeSpan.FromSeconds(3);
private void Window3_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (DateTime.Now.Subtract(mouseDown) > interval)
MessageBox.Show("Mouse was held down for > 3 seconds!");
mouseDown = DateTime.Now;
}
}

The second time this gets called
dispatcherTimer.Tick += dispatcherTimer_Tick; // try without that new EventHandler(...)
a second handled will be attached. So, after the first second, sec will be 2, since the event is called twice.
You can try to dispose and set to null the dispatcherTimer variable on the PreviewMouseUp & create a new instance on the PreviewMouseDown.
Or another option would be, on the PreviewMouseUp, you can
dispatcherTimer.Tick -= dispatcherTimer_Tick;
sec = 0;
-= will detach the event handler.

Related

Refresh DataGrid in silverlight

I have DataGrid with columns inside it.
I want the DataGrid to be refreshed every 3 seconds, with data from the service.
I need that the Scroll will not jump to the top of the DataGrid, every time it refreshes, and stay on the same place of the Scroll. Is it possible?
Here is my code :
<sdk:DataGrid Grid.Row="1" FlowDirection="RightToLeft" ColumnHeaderHeight="32"
AutoGenerateColumns="False" Name="RealTimeReportDataGrid"
RowEditEnded="LinesDataGrid_RowEditEnded" RowHeight="40">
<sdk:DataGrid.Columns>...</sdk:DataGrid.Columns>
</sdk:DataGrid>
This is the code behind:
public RealTimeReport()
{
InitializeComponent();
Loaded += OnViewLoaded;
RealTimeReportService.RealTimeReportServiceClient RTws = new RealTimeReportService.RealTimeReportServiceClient();
RTws.GetRealTimeReportAsync();
RTws.GetRealTimeReportCompleted += new EventHandler<RealTimeReportService.GetRealTimeReportCompletedEventArgs>(RTws_GetRealTimeReportCompleted);
}
void RTws_GetRealTimeReportCompleted(object sender, RealTimeReportService.GetRealTimeReportCompletedEventArgs e)
{
var t = e.Result.ToList();
RealTimeReportDataGrid.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<ShahalDialerRT.RealTimeReportService.RealTimeReport>(e.Result.ToList());
}
private void OnViewLoaded(object sender, RoutedEventArgs e)
{
Start();
}
private void OnUpdaterTimerTick(object sender, EventArgs e)
{
RealTimeReportService.RealTimeReportServiceClient RTws = new RealTimeReportService.RealTimeReportServiceClient();
RTws.GetRealTimeReportAsync();
RTws.GetRealTimeReportCompleted += new EventHandler<RealTimeReportService.GetRealTimeReportCompletedEventArgs>(RTws_GetRealTimeReportCompleted);
}
public void Start()
{
InitializeRefreshDataTimer();
}
public void InitializeRefreshDataTimer()
{
_updaterTimer.Interval = new TimeSpan(0, 0, 0, 0, 3000);
_updaterTimer.Tick += OnUpdaterTimerTick;
_updaterTimer.Start();
}
Thanks ahead.
Update:
#StepUp, this is the only change I made, according to what you said, but still no change :(
void RTws_GetRealTimeReportCompleted(object sender, RealTimeReportService.GetRealTimeReportCompletedEventArgs e)
{
var t = e.Result.ToList();
RealTimeReportDataGrid.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<ShahalDialerRT.RealTimeReportService.RealTimeReport>(e.Result.ToList());
this.RealTimeReportDataGrid.Dispatcher.BeginInvoke(() =>
{
RealTimeReportDataGrid.ScrollIntoView(
RealTimeReportDataGrid.SelectedItem,
RealTimeReportDataGrid.CurrentColumn);
});
//RealTimeReportDataGrid.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<ShahalDialerRT.RealTimeReportService.RealTimeReport>(e.Result.ToList());
//RealTimeReportDataGrid.UpdateLayout();
//RealTimeReportDataGrid.ScrollIntoView(RealTimeReportDataGrid.SelectedItem, RealTimeReportDataGrid.Columns[0]);
}
To refresh every 3 seconds just use Timer class:
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed+=new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval=3000;
aTimer.Enabled=true;
// Specify what you want to happen when the Elapsed event is raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//add new data
}
The Elapsed event will be raised every X amount of seconds, specified in milliseconds by the Interval property on the Timer object. It will call the Event Handler method you specify, in the example above it is OnTimedEvent.
To stay Scroll on the same position in DataGrid:
yourDataGrid.ItemsSource = data;
yourDataGrid.UpdateLayout();
yourDataGrid.ScrollIntoView(theDataGrid.SelectedItem, theDataGrid.Columns[0]);
Update:
yourDataGrid.Dispatcher.BeginInvoke(() =>
{
yourDataGrid.Focus();
yourDataGrid.SelectedItem=whateverYouWant;
yourDataGrid.CurrentColumn=yourDataGrid.Columns[0];
yourDataGrid.ScrollIntoView(yourDataGrid.SelectedItem, yourDataGrid.CurrentColumn);
});
OR:
yourDataGrid.SelectedIndex = 5; // the index you want to select
yourDataGrid.UpdateLayout();
yourDataGrid.ScrollIntoView(Grid.SelectedItem, 0);

View Input Text for a second in TextBox and change to passwordchar

same Question as this one but the last answer is the one i wanted.. I need c# wpf... i tried the last answer but i can't seem to get the interval.. sometimes the key pressed can be seen, and sometimes it doesn't.. how can I get same interval when key press?
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
dispatcherTimer.Start();
}
i tried
dispatcherTimer.Interval = TimeSpan.FromSeconds(5);
but still the same...
EDIT
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
string str = "";
for(int i = 0; i < txtPass.Text.Length; i++)
str += char.ConvertFromUtf32(8226);
txtPass.Text = str;
txtPass.Select(txtPass.Text.Length, 0);
}
You don't need to subscribe to new event handler every time. Just do it one time in the constructor
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += dispatcherTimer_Tick;
dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
In the Keydown event, just reset the timer (Unfortunately we don't have any Reset method)
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
dispatcherTimer.Stop();
dispatcherTimer.Start();
}
As the timer ticks, just Stop the timer and do your work
void dispatcherTimer_Tick(object sender, EventArgs e)
{
dispatcherTimer.Stop();
//your code
}

How to stop a Dispatcher when the event tick?

I need to stop the event connected to the Dispatcher after the event first time tick.
Any idea how to do it.
int closeSeconds = Convert.ToInt32(utility.GetConfiguration("device", "closePopupPrinterAfterSeconds"));
var dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimerCheckPopupPrinter_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, closeSeconds);
dispatcherTimer.Start();
private void dispatcherTimerCheckPopupPrinter_Tick(object sender, EventArgs e)
{
// stop the dispatcherTimer here, so this method will not fire every x seconds
System.Windows.Threading.Dispatcher displatcher = (System.Windows.Threading.Dispatcher)sender;
}
Cast the sender argument to DispatcherTimer, not Dispatcher, and call its Stop method, or set its IsEnabled property to false.
private void dispatcherTimerCheckPopupPrinter_Tick(object sender, EventArgs e)
{
var timer = (DispatcherTimer)sender; // not Dispatcher!
timer.Stop(); // or timer.IsEnabled = false;
}

How do I create a timer in WPF?

I am a newbie in timer in wpf and I need a code that every 5mins there is a message box will pop up. .can anyone help me for the simple code of timer.
That's what I tried so far:
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
private void test()
{
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
// code goes here
}
private void button1_Click(object sender, RoutedEventArgs e)
{
test();
}
In WPF, you use a DispatcherTimer.
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0,5,0);
dispatcherTimer.Start();
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
// code goes here
}
Adding to the above. You use the Dispatch timer if you want the tick events marshalled back to the UI thread. Otherwise I would use System.Timers.Timer.

DispatcherTimer apply interval and execute immediately

Basically when we apply some interval ie 5 sec we have to wait for it.
Is it possible to apply interval and execute timer immediately and don't wait 5 sec?
(I mean the interval time).
Any clue?
Thanks!!
public partial class MainWindow : Window
{
DispatcherTimer timer = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
timer.Tick += new EventHandler(timer_Tick);
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void timer_Tick(object sender, EventArgs e)
{
MessageBox.Show("!!!");
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
timer.Interval = new TimeSpan(0, 0, 5);
timer.Start();
}
}
There are definitely more elegant solutions, but a hacky way is to just call the timer_Tick method after you set the interval initially. That'd be better than setting the interval on every tick.
Initially set the interval to zero and then raise it on a subsequent call.
void timer_Tick(object sender, EventArgs e)
{
((Timer)sender).Interval = new TimeSpan(0, 0, 5);
MessageBox.Show("!!!");
}
could try this:
timer.Tick += Timer_Tick;
timer.Interval = 0;
timer.Start();
//...
public void Timer_Tick(object sender, EventArgs e)
{
if (timer.Interval == 0) {
timer.Stop();
timer.Interval = SOME_INTERVAL;
timer.Start();
return;
}
//your timer action code here
}
Another way could be to use two event handlers (to avoid checking an "if" at every tick):
timer.Tick += Timer_TickInit;
timer.Interval = 0;
timer.Start();
//...
public void Timer_TickInit(object sender, EventArgs e)
{
timer.Stop();
timer.Interval = SOME_INTERVAL;
timer.Tick += Timer_Tick();
timer.Start();
}
public void Timer_Tick(object sender, EventArgs e)
{
//your timer action code here
}
However the cleaner way is what was already suggested:
timer.Tick += Timer_Tick;
timer.Interval = SOME_INTERVAL;
SomeAction();
timer.Start();
//...
public void Timer_Tick(object sender, EventArgs e)
{
SomeAction();
}
public void SomeAction(){
//...
}
That's how I solved it:
dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(DispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 10);
dispatcherTimer.Start();
DispatcherTimer_Tick(dispatcherTimer, new EventArgs());
Works for me without any issues.
Disclaimer: This answer is not for the OP because he wants to use DispatcherTimer
But if you do not have this limitation and you can use another Timer, then there is a cleaner solution
You can use System.Threading.Timer
The most important thing is setting dueTime:0
System.Threading.Timer timer = new Timer(Callback, null, dueTime:0, period:10000);
The documentation of the dueTime is the following
The amount of time to delay before callback is invoked, in milliseconds. Specify Infinite to prevent the timer from starting. Specify zero (0) to start the timer immediately.
and your callback is like this
private void Callback(object? state) =>
{
}
Again this does not use DispatcherTimer but it could solve your problem
Related answer

Categories

Resources