diff options
Diffstat (limited to 'Xamarin.Forms.Platform.WinRT/PickerRenderer.cs')
-rw-r--r-- | Xamarin.Forms.Platform.WinRT/PickerRenderer.cs | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.WinRT/PickerRenderer.cs b/Xamarin.Forms.Platform.WinRT/PickerRenderer.cs new file mode 100644 index 00000000..a7fcbb41 --- /dev/null +++ b/Xamarin.Forms.Platform.WinRT/PickerRenderer.cs @@ -0,0 +1,147 @@ +using System; +using System.ComponentModel; +using System.Threading.Tasks; +using Windows.UI.Core; +using Windows.UI.Xaml.Controls; + +#if WINDOWS_UWP + +namespace Xamarin.Forms.Platform.UWP +#else + +namespace Xamarin.Forms.Platform.WinRT +#endif +{ + public class PickerRenderer : ViewRenderer<Picker, FormsComboBox> + { + bool _isAnimating; + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (Control != null) + { + _isAnimating = false; + Control.SelectionChanged -= OnControlSelectionChanged; + Control.DropDownOpened -= OnDropDownOpenStateChanged; + Control.DropDownClosed -= OnDropDownOpenStateChanged; + Control.OpenAnimationCompleted -= ControlOnOpenAnimationCompleted; + } + } + + base.Dispose(disposing); + } + + protected override void OnElementChanged(ElementChangedEventArgs<Picker> e) + { + if (e.NewElement != null) + { + if (Control == null) + { + SetNativeControl(new FormsComboBox()); + Control.SelectionChanged += OnControlSelectionChanged; + Control.DropDownOpened += OnDropDownOpenStateChanged; + Control.DropDownClosed += OnDropDownOpenStateChanged; + Control.OpenAnimationCompleted += ControlOnOpenAnimationCompleted; + Control.ClosedAnimationStarted += ControlOnClosedAnimationStarted; + } + + Control.ItemsSource = Element.Items; + + UpdateTitle(); + UpdateSelectedIndex(); + } + + base.OnElementChanged(e); + } + + protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) + { + base.OnElementPropertyChanged(sender, e); + + if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName) + UpdateSelectedIndex(); + else if (e.PropertyName == Picker.TitleProperty.PropertyName) + UpdateTitle(); + } + + void ControlOnClosedAnimationStarted(object sender, EventArgs eventArgs) + { + if (!Control.IsFullScreen) + { + // Start refreshing while the control's closing animation runs; + // OnDropDownOpenStateChanged will take care of stopping the refresh + StartAnimationRefresh(); + } + } + + void ControlOnOpenAnimationCompleted(object sender, EventArgs eventArgs) + { + _isAnimating = false; + if (!Control.IsFullScreen) + { + // Force a final redraw after the closing animation has completed + Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged); + } + } + + void OnControlSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (Element != null) + Element.SelectedIndex = Control.SelectedIndex; + } + + void OnDropDownOpenStateChanged(object sender, object o) + { + if (Control.IsDropDownOpen) + { + if (Control.IsOpeningAnimated && !Control.IsFullScreen) + { + // Start running the animation refresh; + // ControlOnOpenAnimationCompleted will take care of stopping it + StartAnimationRefresh(); + } + else + { + Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged); + } + } + else + { + // The ComboBox is now closed; if we were animating the closure, stop + _isAnimating = false; + // and force the final redraw + Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged); + } + } + + /// <summary> + /// Forces redraw of the control during opening/closing animations to provide + /// a smoother sliding animation for the surrounding controls + /// Only applies on the phone and only when there are fewer than 6 items in the picker + /// </summary> + void StartAnimationRefresh() + { + _isAnimating = true; + Task.Factory.StartNew(async () => + { + while (_isAnimating) + { + await Task.Delay(16); + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged)); + } + }); + } + + void UpdateSelectedIndex() + { + Control.SelectedIndex = Element.SelectedIndex; + } + + void UpdateTitle() + { + Control.Header = Element.Title; + } + } +}
\ No newline at end of file |