maui-linux/Xamarin.Forms.Platform.WP8/PickerRenderer.cs

285 строки
7.5 KiB
C#

using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.Phone.Controls;
namespace Xamarin.Forms.Platform.WinPhone
{
public class PickerRenderer : ViewRenderer<Picker, FrameworkElement>
{
bool _isChanging;
FormsListPicker _listPicker;
Brush _defaultBrush;
IElementController ElementController => Element as IElementController;
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
_listPicker = new FormsListPicker();
UpdateAlignment();
UpdateIsEnabled();
base.OnElementChanged(e);
if (e.OldElement != null)
((INotifyCollectionChanged)Element.Items).CollectionChanged -= ItemsCollectionChanged;
((INotifyCollectionChanged)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;
_listPicker.Loaded += (sender, args) => {
// The defaults from the control template won't be available
// right away; we have to wait until after the template has been applied
_defaultBrush = _listPicker.Foreground;
UpdateTextColor();
};
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;
}
else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
{
UpdateIsEnabled();
UpdateTextColor();
}
else if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName)
{
if (Element.SelectedIndex >= 0 && Element.SelectedIndex < Element.Items.Count)
_listPicker.SelectedIndex = Element.SelectedIndex + 1;
}
else if (e.PropertyName == View.HorizontalOptionsProperty.PropertyName)
{
UpdateAlignment();
}
else if (e.PropertyName == Picker.TextColorProperty.PropertyName)
{
UpdateTextColor();
}
}
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
ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
}
else if (oldVal == ListPickerMode.Full && newVal == ListPickerMode.Normal)
{
// PickerPage is now dismissed
ElementController.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;
ElementController.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;
}
void UpdateTextColor()
{
if (!_listPicker.IsEnabled)
{
return;
}
Color color = Element.TextColor;
_listPicker.Foreground = color.IsDefault ? (_defaultBrush ?? color.ToBrush()) : color.ToBrush();
}
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 { };
}
}
}