Search code examples
c#xamluwpvisual-studio-2017timepicker

UWP TimePicker Visual Studio 2017


I am currently working on an app that uses the tool "TimePicker" in Blend for Visual Studio 2017 and I have a question regarding an event I'm trying to find. After a time is selected I wish to have separate events to occur when check-button is pressed that changes the time and if the X-button is pressed to cancel and return from the flyout. I do believe I can use the TimePicker's TimeChanged event to tell whether or not the check button was pressed but I cannot figure out which event would work for if the x-button to cancel was pressed. Does anyone know?


Solution

  • There's no obvious way to do it. There's a Dismiss button in the TimePickerFlyoutPresenter, but getting access to that is not enough. You'll also need to manage keyboard shortcuts, like the [ESC] key.

    You got me a bit curious on how to hack it, so here's what I've come up with so far. Here's a TimePickerDismissal class I hacked-up real quick. The idea is if the TimePicker gains focus after it pushed a popup and it did not report a time change, then it's considered a dismiss.

    public class TimePickerDismissal
    {
        private bool _active;
        private bool _timeChanged;
    
        public event EventHandler Dismissed;
    
        public TimePickerDismissal(TimePicker timer)
        {
            timer.GotFocus += OnTimeGotFocus;
            timer.LostFocus += OnTimeLostFocus;
            timer.TimeChanged += OnTimeChanged;
        }
    
        private void OnTimeGotFocus(object sender, RoutedEventArgs e)
        {
            if (!_active)
            {
                return;
            }
    
            _active = false;
    
            if (!_timeChanged)
            {
                Dismissed?.Invoke(this, EventArgs.Empty);
            }
    
            _timeChanged = false;
        }
    
        private void OnTimeLostFocus(object sender, RoutedEventArgs e)
        {
            var selector = FocusManager.GetFocusedElement() as LoopingSelector;
    
            if (selector == null)
            {
                return;
            }
    
            _active = true;
        }
    
        private void OnTimeChanged(object sender, TimePickerValueChangedEventArgs e)
        {
            _timeChanged = true;
        }
    }
    

    Here's how to use it:

    public sealed partial class MainPage
    {
        public MainPage()
        {
            InitializeComponent();
    
            var dismissal = new TimePickerDismissal(MyTimePicker);
    
            dismissal.Dismissed += OnTimerDismissed;
        }
    
        private void OnTimerDismissed(object sender, EventArgs e)
        {
            Debug.WriteLine("TimePicker dismissed!");
        }
    }
    

    Give that a shot. Let me know if it works for you. You can probably turn this into a behavior actually...