Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Picker Handlers #433

Merged
merged 12 commits into from
Mar 17, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ protected override void OnFocusChangeRequested(object sender, VisualElement.Focu
}
}

[PortHandler("Partially ported, still missing code related to TitleColor, etc.")]
void IPickerRenderer.OnClick()
{
Picker model = Element;
Expand Down Expand Up @@ -168,6 +169,7 @@ protected void UpdateCharacterSpacing()
}
}

[PortHandler("Partially ported, still missing code related to TitleColor, etc.")]
void UpdatePicker()
{
UpdatePlaceHolderText();
Expand Down
7 changes: 7 additions & 0 deletions src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS
{
[PortHandler]
internal class ReadOnlyField : NoCaretField
{
readonly HashSet<string> enableActions;
Expand All @@ -32,6 +33,7 @@ public PickerRenderer()

}

[PortHandler]
protected override UITextField CreateNativeControl()
{
return new ReadOnlyField { BorderStyle = UITextBorderStyle.RoundedRect };
Expand All @@ -56,6 +58,8 @@ public PickerRendererBase()
}

protected abstract override TControl CreateNativeControl();

[PortHandler("Partially ported, still missing code related to TitleColor, etc.")]
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
if (e.OldElement != null)
Expand Down Expand Up @@ -231,6 +235,7 @@ protected internal virtual void UpdatePlaceholder()
protected virtual void UpdateAttributedPlaceholder(NSAttributedString nsAttributedString) =>
Control.AttributedPlaceholder = nsAttributedString;

[PortHandler]
void UpdatePicker()
{
var selectedIndex = Element.SelectedIndex;
Expand Down Expand Up @@ -266,6 +271,7 @@ void UpdatePickerNativeSize(string oldText)
((IVisualElementController)Element).NativeSizeChanged();
}

[PortHandler]
void UpdatePickerSelectedIndex(int formsIndex)
{
var source = (PickerSource)_picker.Model;
Expand Down Expand Up @@ -334,6 +340,7 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}

[PortHandler]
class PickerSource : UIPickerViewModel
{
PickerRendererBase<TControl> _renderer;
Expand Down
19 changes: 19 additions & 0 deletions src/Controls/samples/Controls.Sample/Pages/MainPage.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using Maui.Controls.Sample.ViewModel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui;
Expand Down Expand Up @@ -113,6 +115,23 @@ void SetupMauiLayout()
placeholderSearchBar.Placeholder = "Placeholder";
verticalStack.Add(placeholderSearchBar);


var monkeyList = new List<string>
{
"Baboon",
"Capuchin Monkey",
"Blue Monkey",
"Squirrel Monkey",
"Golden Lion Tamarin",
"Howler Monkey",
"Japanese Macaque"
};

var picker = new Picker { Title = "Select a monkey" };

picker.ItemsSource = monkeyList;
verticalStack.Add(picker);

verticalStack.Add(new Slider());

verticalStack.Add(new Stepper());
Expand Down
7 changes: 7 additions & 0 deletions src/Controls/src/Core/HandlerImpl/Picker.Impl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Microsoft.Maui.Controls
{
public partial class Picker : IPicker
{

}
}
2 changes: 1 addition & 1 deletion src/Controls/src/Core/Picker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace Microsoft.Maui.Controls
{
public class Picker : View, IFontElement, ITextElement, ITextAlignmentElement, IElementConfiguration<Picker>
public partial class Picker : View, IFontElement, ITextElement, ITextAlignmentElement, IElementConfiguration<Picker>
{
public static readonly BindableProperty TextColorProperty = TextElement.TextColorProperty;

Expand Down
14 changes: 14 additions & 0 deletions src/Core/src/Core/IPicker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Collections;
using System.Collections.Generic;

namespace Microsoft.Maui
{
public interface IPicker : IView
{
string Title { get; }
IList<string> Items { get; }
IList ItemsSource { get; }
Comment on lines +9 to +10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these two concepts mean anything at the core layer? This feels a bit binding-y. Also, how will Comet do this? Are we maybe forcing something?

int SelectedIndex { get; set; }
object? SelectedItem { get; set; }
}
}
112 changes: 112 additions & 0 deletions src/Core/src/Handlers/Picker/PickerHandler.Android.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System;
using System.Collections.Specialized;
using System.Linq;
using Android.App;
using AResource = Android.Resource;

namespace Microsoft.Maui.Handlers
{
public partial class PickerHandler : AbstractViewHandler<IPicker, MauiPicker>
{
AlertDialog? _dialog;

protected override MauiPicker CreateNativeView() =>
new MauiPicker(Context);

protected override void ConnectHandler(MauiPicker nativeView)
{
nativeView.FocusChange += OnFocusChange;
nativeView.Click += OnClick;

if (VirtualView != null && VirtualView.Items is INotifyCollectionChanged notifyCollection)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this have been ItemsSource?

notifyCollection.CollectionChanged += OnCollectionChanged;

base.ConnectHandler(nativeView);
}

protected override void DisconnectHandler(MauiPicker nativeView)
{
nativeView.FocusChange -= OnFocusChange;
nativeView.Click -= OnClick;

if (VirtualView != null && VirtualView.Items is INotifyCollectionChanged notifyCollection)
notifyCollection.CollectionChanged -= OnCollectionChanged;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we unsubscribing when the Items/ItemsSource property changes? Like the whole list is assigned a new object?


base.DisconnectHandler(nativeView);
}
public static void MapTitle(PickerHandler handler, IPicker picker)
{
handler.TypedNativeView?.UpdateTitle(picker);
}

public static void MapSelectedIndex(PickerHandler handler, IPicker picker)
{
handler.TypedNativeView?.UpdateSelectedIndex(picker);
}

void OnFocusChange(object? sender, global::Android.Views.View.FocusChangeEventArgs e)
{
if (TypedNativeView == null)
return;

if (e.HasFocus)
{
if (TypedNativeView.Clickable)
TypedNativeView.CallOnClick();
else
OnClick(TypedNativeView, EventArgs.Empty);
}
else if (_dialog != null)
{
_dialog.Hide();
TypedNativeView.ClearFocus();
_dialog = null;
}
}

void OnClick(object? sender, EventArgs e)
{
if (_dialog == null && VirtualView != null)
{
using (var builder = new AlertDialog.Builder(Context))
{
builder.SetTitle(VirtualView.Title ?? string.Empty);

string[] items = VirtualView.Items.ToArray();

builder.SetItems(items, (s, e) =>
{
var selectedIndex = e.Which;
VirtualView.SelectedIndex = selectedIndex;
TypedNativeView?.UpdatePicker(VirtualView);
});

builder.SetNegativeButton(AResource.String.Cancel, (o, args) => { });

_dialog = builder.Create();
}

if (_dialog == null)
return;

_dialog.SetCanceledOnTouchOutside(true);

_dialog.DismissEvent += (sender, args) =>
{
_dialog.Dispose();
_dialog = null;
};

_dialog.Show();
}
}

void OnCollectionChanged(object? sender, EventArgs e)
{
if (VirtualView == null || TypedNativeView == null)
return;

TypedNativeView.UpdatePicker(VirtualView);
}
}
}
12 changes: 12 additions & 0 deletions src/Core/src/Handlers/Picker/PickerHandler.Standard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace Microsoft.Maui.Handlers
{
public partial class PickerHandler : AbstractViewHandler<IPicker, object>
{
protected override object CreateNativeView() => throw new NotImplementedException();

public static void MapTitle(PickerHandler handler, IPicker view) { }
public static void MapSelectedIndex(PickerHandler handler, IPicker view) { }
}
}
21 changes: 21 additions & 0 deletions src/Core/src/Handlers/Picker/PickerHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Microsoft.Maui.Handlers
{
public partial class PickerHandler
{
public static PropertyMapper<IPicker, PickerHandler> PickerMapper = new PropertyMapper<IPicker, PickerHandler>(ViewHandler.ViewMapper)
{
[nameof(IPicker.Title)] = MapTitle,
[nameof(IPicker.SelectedIndex)] = MapSelectedIndex
};

public PickerHandler() : base(PickerMapper)
{

}

public PickerHandler(PropertyMapper mapper) : base(mapper)
{

}
}
}
Loading