You know that little indicator in a chat that shows if someone is currently typing? I am working on a new post (coming soon, link will be here) that uses SignalR to communicate who is currently typing in a chat room along with the messages themselves.
To determine who is typing, I use a timer and the TextChanged
event. The timer logic itself is straightforward, in the TextChanged
event starts a timer.
- The first
TextChanged
event starts a timer. - If the
TextChanged
event fires again before the timer’sElapsed
event, the timer is stopped and restarted. - If the Timer’s
Elapsed
event is fired first, then the user has stopped typing.
This code is a bit tedious to implement over and over again, so why not just build it into the control itself and invoke a custom TypingStarted
and TypingEnded
event? Enjoy!
public class TimedEntry : Entry, IDisposable { private readonly System.Timers.Timer timer; public TimedChatEntry() { TextChanged += TimedChatEntry_TextChanged; timer = new System.Timers.Timer(1000); timer.Elapsed += timer_Elapsed; } public event EventHandler<EventArgs> TypingStarted; public event EventHandler<EventArgs> TypingEnded; private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs args) { if (timer == null) return; timer?.Stop(); Device.BeginInvokeOnMainThread(() => TypingEnded?.Invoke(this, new EventArgs())); } private void TimedChatEntry_TextChanged(object sender, TextChangedEventArgs e) { if (timer == null) return; if (!timer.Enabled) { timer?.Start(); Device.BeginInvokeOnMainThread(() => TypingStarted?.Invoke(this, new EventArgs())); } else { timer.Stop(); timer.Start(); } } public void Dispose() { if (timer != null) { timer.Elapsed -= timer_Elapsed; } timer?.Dispose(); } }
Here’s an example that uses a SignalR service:
<TimedEntry TypingStarted="TimedChatEntry_OnTypingStarted" TypingEnded="TimedChatEntry_OnTypingEnded"/>
private async void TimedChatEntry_OnTypingStarted(object sender, EventArgs e) { if (service != null) await service.SendTyperAsync(me.Name, true); } private async void TimedChatEntry_OnTypingEnded(object sender, EventArgs e) { if (service != null) await service.SendTyperAsync(me.Name, false); }
You can see the entire thing in action, including the SignalR Hub project, here on GitHub: SignalR Chat Room Demo.