diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 13:02:25 -0700 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 16:13:41 -0700 |
commit | 17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch) | |
tree | b5e5073a2a7b15cdbe826faa5c763e270a505729 /Xamarin.Forms.Platform.WP8/PickerRenderer.cs | |
download | xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.gz xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.bz2 xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.zip |
Initial import
Diffstat (limited to 'Xamarin.Forms.Platform.WP8/PickerRenderer.cs')
-rw-r--r-- | Xamarin.Forms.Platform.WP8/PickerRenderer.cs | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.WP8/PickerRenderer.cs b/Xamarin.Forms.Platform.WP8/PickerRenderer.cs new file mode 100644 index 00000000..f9cd2d81 --- /dev/null +++ b/Xamarin.Forms.Platform.WP8/PickerRenderer.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Reflection; +using System.Windows; +using System.Windows.Controls; +using Microsoft.Phone.Controls; + +namespace Xamarin.Forms.Platform.WinPhone +{ + public class PickerRenderer : ViewRenderer<Picker, FrameworkElement> + { + bool _isChanging; + + FormsListPicker _listPicker; + + protected override void OnElementChanged(ElementChangedEventArgs<Picker> e) + { + _listPicker = new FormsListPicker(); + + UpdateAlignment(); + UpdateIsEnabled(); + + base.OnElementChanged(e); + + if (e.OldElement != null) + ((ObservableList<string>)Element.Items).CollectionChanged -= ItemsCollectionChanged; + + ((ObservableList<string>)Element.Items).CollectionChanged += ItemsCollectionChanged; + + _listPicker.ItemTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["PickerItemTemplate"]; + _listPicker.FullModeItemTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["PickerFullItemTemplate"]; + _listPicker.ExpansionMode = ExpansionMode.FullScreenOnly; + _listPicker.Items.Add(new ItemViewModel(" ") { MaxHeight = 0 }); + + _listPicker.ListPickerModeChanged += ListPickerModeChanged; + + var grid = new System.Windows.Controls.Grid { Children = { _listPicker }, MaxWidth = Device.Info.PixelScreenSize.Width }; + SetNativeControl(grid); + + UpdatePicker(); + _listPicker.SelectionChanged += PickerSelectionChanged; + } + + protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) + { + base.OnElementPropertyChanged(sender, e); + if (e.PropertyName == Picker.TitleProperty.PropertyName) + _listPicker.FullModeHeader = Element.Title; + + if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName) + UpdateIsEnabled(); + + if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName) + { + if (Element.SelectedIndex >= 0 && Element.SelectedIndex < Element.Items.Count) + _listPicker.SelectedIndex = Element.SelectedIndex + 1; + } + + if (e.PropertyName == View.HorizontalOptionsProperty.PropertyName) + UpdateAlignment(); + } + + protected override void OnGotFocus(object sender, RoutedEventArgs args) + { + // Do nothing. ListPickerModeChanged is handling the IsFocusProperty setter + // Required because FrameworkElement.GotFocus and FrameworkElement.LostFocus () are fired by ListPicker.Open () + } + + protected override void OnLostFocus(object sender, RoutedEventArgs args) + { + // Do nothing. ListPickerModeChanged is handling the IsFocusProperty setter + // Required because FrameworkElement.GotFocus and FrameworkElement.LostFocus () are fired by ListPicker.Open () + } + + protected override void UpdateNativeWidget() + { + base.UpdateNativeWidget(); + UpdateIsEnabled(); + } + + internal override void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args) + { + if (Control == null) + return; + + if (args.Focus) + args.Result = OpenPickerPage(); + else + { + args.Result = ClosePickerPage(); + UnfocusControl(_listPicker); + } + } + + bool ClosePickerPage() + { + FieldInfo pickerPageField = typeof(ListPicker).GetField("_listPickerPage", BindingFlags.NonPublic | BindingFlags.Instance); + var pickerPage = pickerPageField.GetValue(Control) as ListPickerPage; + typeof(ListPickerPage).InvokeMember("ClosePickerPage", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, Type.DefaultBinder, pickerPage, null); + + return true; + } + + void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + UpdateItems(); + } + + void ListPickerModeChanged(object sender, DependencyPropertyChangedEventArgs e) + { + if (e.OldValue == null || e.NewValue == null) + return; + + var oldVal = (ListPickerMode)e.OldValue; + var newVal = (ListPickerMode)e.NewValue; + + if (oldVal == ListPickerMode.Normal && newVal == ListPickerMode.Full) + { + // Picker Page is now showing + ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true); + } + else if (oldVal == ListPickerMode.Full && newVal == ListPickerMode.Normal) + { + // PickerPage is now dismissed + ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false); + } + } + + bool OpenPickerPage() + { + bool result = _listPicker.Open(); + + if (result) + return true; + + return false; + } + + void PickerSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (_isChanging) + return; + + var picker = (ListPicker)sender; + + // initializing picker + if (picker.SelectedIndex == -1) + return; + + int elementSelectedIndex = picker.SelectedIndex - 1; + ((IElementController)Element).SetValueFromRenderer(Picker.SelectedIndexProperty, elementSelectedIndex); + } + + void UpdateAlignment() + { + if (Element.HorizontalOptions.Alignment != LayoutAlignment.Fill) + _listPicker.HorizontalAlignment = HorizontalAlignment.Left; + } + + void UpdateIsEnabled() + { + if (_listPicker != null) + _listPicker.IsEnabled = Element.IsEnabled; + } + + void UpdateItems() + { + // supress notification of non-user generated events (e.g. adding\syncing list values) + _isChanging = true; + FormsListPicker picker = _listPicker; + // add/remove slots from control to match element + while (picker.Items.Count < Element.Items.Count + 1) + picker.Items.Add(new ItemViewModel(string.Empty)); + + while (picker.Items.Count > Element.Items.Count + 1) + picker.Items.RemoveAt(picker.Items.Count - 1); + + // update all control values to match element values + for (var i = 0; i < Element.Items.Count; i++) + { + var item = (ItemViewModel)picker.Items[i + 1]; + if (item.Data == Element.Items[i]) + continue; + + item.Data = Element.Items[i]; + } + + picker.SelectedIndex = Element.SelectedIndex + 1; + + _isChanging = false; + } + + void UpdatePicker() + { + _listPicker.FullModeHeader = Element.Title; + UpdateItems(); + _listPicker.SelectedIndex = Element.SelectedIndex + 1; + } + + class ItemViewModel : INotifyPropertyChanged + { + string _data; + int _maxHeight; + float _opacity; + + public ItemViewModel(string item) + { + _opacity = 1; + _data = item; + _maxHeight = int.MaxValue; + } + + public string Data + { + get { return _data; } + set + { + if (value == _data) + return; + + _data = value; + PropertyChanged(this, new PropertyChangedEventArgs("Data")); + } + } + + public int MaxHeight + { + get { return _maxHeight; } + set + { + if (value == _maxHeight) + return; + + _maxHeight = value; + PropertyChanged(this, new PropertyChangedEventArgs("MaxHeight")); + } + } + + public float Opacity + { + get { return _opacity; } + set + { + if (value == _opacity) + return; + + _opacity = value; + PropertyChanged(this, new PropertyChangedEventArgs("Opacity")); + } + } + + public event PropertyChangedEventHandler PropertyChanged = delegate { }; + } + } +}
\ No newline at end of file |