WPF Dispatchertimer tick increments, - wpf

I am making a countdown clock using dispatchertimer and timespan in WPF.
I have a button to start the countdown and a button to stop the countdown. When I hit the start button again it has doubled the interval from one second to two seconds. I display the counting in a textbox. What is wrong?
The code is simple:
public partial class MainWindow : Window
{
private DispatcherTimer DPtimerA;
private TimeSpan timeA;
public MainWindow()
{
InitializeComponent();
DPtimerA = new DispatcherTimer();
DPtimerA.Interval = new TimeSpan(0, 0, 1);
timeA = TimeSpan.FromSeconds(21);
}
private void DPtimerA_Tick(object sender, EventArgs e)
{
timeA = timeA.Add(TimeSpan.FromSeconds(-1));
txtClockA.Text = timeA.ToString("c");
if (timeA == TimeSpan.Zero) DPtimerA.Stop();
}
private void btnStartA_Click(object sender, RoutedEventArgs e)
{
DPtimerA.Tick += DPtimerA_Tick;
DPtimerA.Start();
}
private void btnStopA_Click(object sender, RoutedEventArgs e)
{
DPtimerA.Stop();
}
}
}

Change it like this:
private void btnStartA_Click(object sender, RoutedEventArgs e)
{
DPtimerA.Tick -= DPtimerA_Tick;
DPtimerA.Tick += DPtimerA_Tick;
DPtimerA.Start();
}

Make DispatcherTimer a readonly field that you initialize and hook up an event handler to once:
public partial class MainWindow : Window
{
private readonly DispatcherTimer DPtimerA =
new DispatcherTimer() { Interval = new TimeSpan(0, 0, 1) };
private TimeSpan timeA = TimeSpan.FromSeconds(21);
public MainWindow()
{
InitializeComponent();
DPtimerA.Tick += DPtimerA_Tick;
}
private void DPtimerA_Tick(object sender, EventArgs e)
{
timeA = timeA.Add(TimeSpan.FromSeconds(-1));
txtClockA.Text = timeA.ToString("c");
if (timeA == TimeSpan.Zero)
DPtimerA.Stop();
}
private void btnStartA_Click(object sender, RoutedEventArgs e)
{
DPtimerA.Start();
}
private void btnStopA_Click(object sender, RoutedEventArgs e)
{
DPtimerA.Stop();
}
}

Related

populating a listbox from another window, but on second attempt the list is replaced instead of added

I'm building a task list application.
From my main window, I click on the add button. The program generates a new Window,and I compete the form and close it with the complete button.
My listbox in the main window has been populated with the tasks that I have entered.
The problem is, when I do this again, the listbox items are replaced with new items instead of the ones being added.
MainWindow.cs
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
List<Task> allTasks = new List<Task>();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
}
private void addTaskBtn_Click(object sender, RoutedEventArgs e)
{
NewTaskWindow newTaskWindow = new NewTaskWindow();
newTaskWindow.Owner = this;
newTaskWindow.Show();
}
private void editTaskBtn_Click(object sender, RoutedEventArgs e)
{
}
private void searchBtn_Click(object sender, RoutedEventArgs e)
{
}
private void AddUserBtn_Click(object sender, RoutedEventArgs e)
{
}
private void markCompleteButton_Click(object sender, RoutedEventArgs e)
{
}
private void deleteTaskBtn_Click(object sender, RoutedEventArgs e)
{
}
}
NewTaskWindow.cs
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
namespace Task_Managment
{
public partial class NewTaskWindow : Window
{
Task newTask = new Task();
public NewTaskWindow()
{
InitializeComponent();
}
ObservableCollection<Task> AllTasks = new ObservableCollection<Task>();
ObservableCollection<Task> taskList = new ObservableCollection<Task>();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
string[] taskType = new string[3];
taskType[0] = "Home";
taskType[1] = "College";
taskType[2] = "Work";
CataCombo.ItemsSource = taskType;
}
public void completeBtn_Click(object sender, RoutedEventArgs e)
{
List<Task> allTasks = new List<Task>();
newTask = new Task
{
Title = titletxBx.Text,
Description = DesctxBx.Text,
Priority = prioritytxBx.Text,
Catagory = CataCombo.Text,
taskDate = calander.SelectedDate.Value
};
taskList.Add(newTask);
MainWindow main = Owner as MainWindow;
main.taskListBox.ItemsSource = taskList;
titletxBx.Clear();
prioritytxBx.Clear();
DesctxBx.Clear();
responsibilitytxBx.Clear();
}
private void finishBtn_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}
You need to save the TaskList somewhere, make the tasklist definition public to get acces from the main window and pass it from the main window when you load the new form:
observableCollection<Task> AllTasks = new ObservableCollection<Task>();
public ObservableCollection<Task> taskList = new ObservableCollection<Task>();
public NewTaskWindow(ObservableCollection<Task> taskList)
{
InitializeComponent();
this.tasklist = tasklist
}
After that, you only need to retrieve and send it from the main to the new window
private void addTaskBtn_Click(object sender, RoutedEventArgs e)
{
NewTaskWindow newTaskWindow = new NewTaskWindow(tasklist);
newTaskWindow.Owner = this;
newTaskWindow.Show();
tasklist = newTaskWindow.tasklist;
}
In the main window you must initialize it for the first run if not you will get an error:
ObservableCollection<Task> taskList = new ObservableCollection<Task>();
public MainWindow()
{
InitializeComponent();
}
....
Obviously this only save for the time you have the program open, when you close the program it will lose all the info. So if you are interested in that also, save in a file and load from it.

I get confused with Form.Close()

So I link delegate from Form2 to This_Hide() fuction in Form1, then i link delegate from Form3 to delegate in Form2(which link to function in Form1 as I said) but I get confused that it still work although Form2 is CLOSED when I making instance of Form3. If Form.Close() method closes Form2 and dispose it how delegate from Form3 can still call function(delegate) from Form2..?
namespace TestingMachine
{
public delegate void FxDelegate();
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Form2 fr2 = new Form2();
fr2.Delegate_Father_Hide = new FxDelegate(This_Hide);
fr2.Show();
}
public void This_Hide()
{
this.Hide();
}
}
}
namespace TestingMachine
{
public partial class Form2 : Form
{
public FxDelegate Delegate_Father_Hide;
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Form3 fr3 = new Form3();
fr3.Delegate_Hide_Grandfather = new FxDelegate(Hide_Grandfather);
fr3.Show();
this.Close();
}
public void Hide_Grandfather()
{
Delegate_Father_Hide();
}
}
}
namespace TestingMachine
{
public partial class Form3 : Form
{
public FxDelegate Delegate_Hide_Grandfather;
public Form3()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Delegate_Hide_Grandfather();
}
}
}

Cannot set the value of a global variable

Im pretty new to programming, but im very eager to get more into this stuff, and in particular, c#. I have a made some code for an autotyper (spam bot if i may), only to be used as a goal for me to create. Essentially, what i want the program to do, is as following:
When i start my Form1, the global variable "_timerValue" is set to
1000
When i hit Start button, the text from the textbox on will be sent at
the interval of "_timerValue"
When i hit the Speed button, Form2 will show.
When i hit very fast, "_timerValue" is set to 5000 (testing purposes)
Form1 code:
public partial class Form1 : Form
{
static class TimerIntervalValue
{
Form2 f2 = new Form2();
TimerIntervalValue = f2._timerValue;
}
public Form1()
{
InitializeComponent();
f2._timerValue = "1000";
}
public void timer1_Tick(object sender, EventArgs e)
{
SendKeys.Send(textBox1.Text);
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
MessageBox.Show(f2._timerValue);
timer1.Interval = Convert.ToInt32(f2._timerValue);
if (timer1.Enabled == false)
{
timer1.Enabled = true;
textBox1.Enabled = false;
button1.Text = ("Stop");
}
else if (timer1.Enabled == true)
{
timer1.Enabled = false;
textBox1.Enabled = true;
button1.Text = ("Start");
}
}
private void button2_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.Show();
}
}
Form2 code:
public partial class Form2 : Form
{
public string TimerValue;
public string _timerValue
{
get { return TimerValue; }
set { TimerValue = value; }
}
public Form2()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2._timerValue = "5000";
}
}
I originally tried to create a Form2 instance just under "InitializeComponent();" in Form1, but that didnt seem to be accessible through the other funtions.
I just know its something very simple like im using the wrong class to create the Form2 instance or something like that ...
Anyway, thank you in advance
Just mark TimerValue and _timerValue as static. Then you don't need to use
Form2 f2 = new Form2(); or Form2 frm2 = new Form2();
anymore. In Form 1, just use Form2._timerValue instead of f2._timerValue. In Form 2, just change:
public void button1_Click(object sender, EventArgs e)
{
_timerValue = "5000";
}

Modify WPF dependency property when pressing key

I have a WPF UserControl with a certain dependency property DepProp.
I would like this property to be modified when I press Shift or Alt, and to return to the previous value when releasing the keys.
What I want is similar to a trigger, but I don't know if it's possible to set the condition to be something like "Shift key is pressed".
I know that it's possible to specify KeyBindings for the control, as far as I understood they can execute a command when a key is pressed, but don't restore the previous vlaue when the key is released.
Any idea on how to do this?
You could create an attached behavior that you can affix to some "scope" element (e.g., your UserControl) that will maintain an attached read-only property that gets inherited down the tree. Then you can simply add a Trigger on the attached property.
public sealed class AltShiftHotKeyBehavior : Behavior<FrameworkElement>
{
private const ModifierKeys AltShift = ModifierKeys.Alt | ModifierKeys.Shift;
private static readonly DependencyPropertyKey IsAltShiftPressedPropertyKey =
DependencyProperty.RegisterAttachedReadOnly(
"IsAltShiftPressed",
typeof(bool),
typeof(AltShiftHotKeyBehavior),
new FrameworkPropertyMetadata(
false,
FrameworkPropertyMetadataOptions.Inherits));
public static readonly DependencyProperty IsAltShiftPressedProperty =
IsAltShiftPressedPropertyKey.DependencyProperty;
public static bool GetIsAltShiftPressed(DependencyObject element)
{
return (bool)element.GetValue(IsAltShiftPressedProperty);
}
protected override void OnAttached()
{
base.OnAttached();
var element = this.AssociatedObject;
element.AddHandler(
FrameworkElement.LoadedEvent,
(RoutedEventHandler)OnLoaded,
handledEventsToo: true);
element.AddHandler(
FrameworkElement.UnloadedEvent,
(RoutedEventHandler)OnUnloaded,
handledEventsToo: true);
element.AddHandler(
UIElement.PreviewKeyDownEvent,
(KeyEventHandler)OnKey,
handledEventsToo: true);
element.AddHandler(
UIElement.PreviewKeyUpEvent,
(KeyEventHandler)OnKey,
handledEventsToo: true);
element.AddHandler(
UIElement.LostKeyboardFocusEvent,
(KeyboardFocusChangedEventHandler)OnLostKeyboardFocus,
handledEventsToo: true);
var window = element as Window;
if (window != null)
{
window.Activated += OnWindowActivated;
window.Deactivated += OnWindowDeactivated;
}
CheckToggledState();
}
protected override void OnDetaching()
{
ClearToggledState();
base.OnDetaching();
var element = this.AssociatedObject;
element.RemoveHandler(
FrameworkElement.LoadedEvent,
(RoutedEventHandler)OnLoaded);
element.RemoveHandler(
FrameworkElement.UnloadedEvent,
(RoutedEventHandler)OnUnloaded);
element.RemoveHandler(
UIElement.PreviewKeyDownEvent,
(KeyEventHandler)OnKey);
element.RemoveHandler(
UIElement.PreviewKeyUpEvent,
(KeyEventHandler)OnKey);
element.RemoveHandler(
UIElement.LostKeyboardFocusEvent,
(KeyboardFocusChangedEventHandler)OnLostKeyboardFocus);
var window = element as Window;
if (window != null)
{
window.Activated -= OnWindowActivated;
window.Deactivated -= OnWindowDeactivated;
}
}
private void CheckToggledState()
{
var element = this.AssociatedObject;
if (element.IsLoaded &&
element.IsKeyboardFocusWithin &&
Keyboard.PrimaryDevice.Modifiers == AltShift)
{
element.SetValue(IsAltShiftPressedPropertyKey, true);
}
else
{
element.ClearValue(IsAltShiftPressedPropertyKey);
}
}
private void ClearToggledState()
{
this.AssociatedObject.ClearValue(IsAltShiftPressedPropertyKey);
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
CheckToggledState();
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
ClearToggledState();
}
private void OnWindowActivated(object sender, EventArgs e)
{
CheckToggledState();
}
private void OnWindowDeactivated(object sender, EventArgs e)
{
ClearToggledState();
}
private void OnLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
CheckToggledState();
}
private void OnKey(object sender, KeyEventArgs e)
{
CheckToggledState();
}
}

How to detect a Touch Press and Hold gesture in a WPF application?

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);
}
}

Resources