diff --git a/Ooui.Forms/Cells/CellRenderer.cs b/Ooui.Forms/Cells/CellRenderer.cs new file mode 100644 index 0000000..2f3492f --- /dev/null +++ b/Ooui.Forms/Cells/CellRenderer.cs @@ -0,0 +1,71 @@ +using Ooui.Forms.Extensions; +using System; +using Xamarin.Forms; + +namespace Ooui.Forms.Cells +{ + public class CellRenderer : IRegisterable + { + private EventHandler _onForceUpdateSizeRequested; + + static readonly BindableProperty RealCellProperty = + BindableProperty.CreateAttached("RealCell", typeof(Div), + typeof(Cell), null); + + public virtual CellView GetCell(Cell item, CellView reusableView, List listView) + { + var nativeCell = reusableView as CellView ?? GetCellInstance(item); + + nativeCell.Cell = item; + + WireUpForceUpdateSizeRequested(item, nativeCell); + UpdateBackground(nativeCell, item); + + return nativeCell; + } + + internal static CellView GetRealCell(BindableObject cell) + { + return (CellView)cell.GetValue(RealCellProperty); + } + + internal static void SetRealCell(BindableObject cell, CellView renderer) + { + cell.SetValue(RealCellProperty, renderer); + } + + protected virtual CellView GetCellInstance(Cell item) + { + return new CellView(); + } + + protected virtual void OnForceUpdateSizeRequest(Cell cell, CellView nativeCell) + { + nativeCell.Style.Height = (int)cell.RenderHeight; + } + + protected void UpdateBackground(CellView tableViewCell, Cell cell) + { + var defaultColor = Xamarin.Forms.Color.White.ToOouiColor(); + Color backgroundColor = defaultColor; + + if (cell.RealParent is VisualElement element) + backgroundColor = element.BackgroundColor == + Xamarin.Forms.Color.Default ? backgroundColor : element.BackgroundColor.ToOouiColor(); + + tableViewCell.Style.BackgroundColor = backgroundColor; + } + + protected void WireUpForceUpdateSizeRequested(Cell cell, CellView nativeCell) + { + cell.ForceUpdateSizeRequested -= _onForceUpdateSizeRequested; + + _onForceUpdateSizeRequested = (sender, e) => + { + OnForceUpdateSizeRequest(cell, nativeCell); + }; + + cell.ForceUpdateSizeRequested += _onForceUpdateSizeRequested; + } + } +} diff --git a/Ooui.Forms/Cells/CellView.cs b/Ooui.Forms/Cells/CellView.cs new file mode 100644 index 0000000..e4c72be --- /dev/null +++ b/Ooui.Forms/Cells/CellView.cs @@ -0,0 +1,84 @@ +using System; +using System.ComponentModel; +using Xamarin.Forms; + +namespace Ooui.Forms.Cells +{ + public class CellView : Div, INativeElementView + { + private Cell _cell; + + public Action PropertyChanged; + + public CellView() + { + CreateUI(); + } + + public Cell Cell + { + get { return _cell; } + set + { + if (_cell == value) + return; + + if (_cell != null) + Device.BeginInvokeOnMainThread(_cell.SendDisappearing); + + _cell = value; + + if (_cell != null) + Device.BeginInvokeOnMainThread(_cell.SendAppearing); + } + } + + public Div FirstCol { get; private set; } + + public Div SecondCol { get; private set; } + + public Div ThirdCol { get; private set; } + + public Label TextLabel { get; private set; } + + public Label DetailTextLabel { get; private set; } + + public Image ImageView { get; private set; } + + public Div CustomView { get; private set; } + + public virtual Xamarin.Forms.Element Element => Cell; + + public void HandlePropertyChanged(object sender, PropertyChangedEventArgs e) + { + PropertyChanged?.Invoke(this, e); + } + + private void CreateUI() + { + Style.Width = "100%"; + Style.Display = "flex"; + + FirstCol = new Div(); + AppendChild(FirstCol); + + SecondCol = new Div(); + AppendChild(SecondCol); + + ThirdCol = new Div(); + AppendChild(ThirdCol); + + ImageView = new Image(); + FirstCol.AppendChild(ImageView); + + TextLabel = new Label(); + SecondCol.AppendChild(TextLabel); + + DetailTextLabel = new Label(); + SecondCol.AppendChild(DetailTextLabel); + + CustomView = new Div(); + ThirdCol.AppendChild(CustomView); + } + } +} diff --git a/Ooui.Forms/Cells/EntryCellRenderer.cs b/Ooui.Forms/Cells/EntryCellRenderer.cs new file mode 100644 index 0000000..f0edb6a --- /dev/null +++ b/Ooui.Forms/Cells/EntryCellRenderer.cs @@ -0,0 +1,104 @@ +using Ooui.Forms.Extensions; +using System; +using System.ComponentModel; +using Xamarin.Forms; + +namespace Ooui.Forms.Cells +{ + public class EntryCellRenderer : CellRenderer + { + private static Cell _cell; + + public override CellView GetCell(Cell item, CellView reusableView, List listView) + { + TextInput nativeEntry = null; + + var nativeEntryCell = base.GetCell(item, reusableView, listView); + + if (nativeEntryCell == null) + nativeEntryCell = new CellView(); + else + { + nativeEntryCell.Cell.PropertyChanged -= OnCellPropertyChanged; + + nativeEntry = nativeEntryCell.CustomView.FirstChild as TextInput; + if (nativeEntry != null) + { + nativeEntryCell.CustomView.RemoveChild(nativeEntry); + nativeEntry.Change -= OnTextChanged; + } + } + + SetRealCell(item, nativeEntryCell); + + if (nativeEntry == null) + nativeEntryCell.CustomView.AppendChild(nativeEntry = new TextInput()); + + var entryCell = (EntryCell)item; + + nativeEntryCell.Cell = item; + nativeEntryCell.SecondCol.Style.Width = "25%"; + _cell = nativeEntryCell.Cell; + + nativeEntryCell.Cell.PropertyChanged += OnCellPropertyChanged; + nativeEntry.Change += OnTextChanged; + + WireUpForceUpdateSizeRequested(item, nativeEntryCell); + + UpdateBackground(nativeEntryCell, entryCell); + UpdateLabel(nativeEntryCell, entryCell); + UpdateText(nativeEntryCell, entryCell); + UpdatePlaceholder(nativeEntryCell, entryCell); + UpdateLabelColor(nativeEntryCell, entryCell); + + return nativeEntryCell; + } + + private static void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e) + { + var entryCell = (EntryCell)sender; + var realCell = (CellView)GetRealCell(entryCell); + + if (e.PropertyName == EntryCell.LabelProperty.PropertyName) + UpdateLabel(realCell, entryCell); + else if (e.PropertyName == EntryCell.TextProperty.PropertyName) + UpdateText(realCell, entryCell); + else if (e.PropertyName == EntryCell.PlaceholderProperty.PropertyName) + UpdatePlaceholder(realCell, entryCell); + else if (e.PropertyName == EntryCell.LabelColorProperty.PropertyName) + UpdateLabelColor(realCell, entryCell); + } + + private static void UpdateLabel(CellView cell, EntryCell entryCell) + { + cell.TextLabel.Text = entryCell.Label ?? string.Empty; + } + + private static void UpdateLabelColor(CellView cell, EntryCell entryCell) + { + cell.TextLabel.Style.Color = entryCell.LabelColor.ToOouiColor(); + } + + private static void UpdatePlaceholder(CellView cell, EntryCell entryCell) + { + if (cell.CustomView.FirstChild is TextInput textInput) + textInput.Placeholder = entryCell.Placeholder ?? string.Empty; + } + + private static void UpdateText(CellView cell, EntryCell entryCell) + { + if (cell.CustomView.FirstChild is TextInput textInput) + textInput.Text = entryCell.Text ?? string.Empty; + } + + private static void OnTextChanged(object sender, EventArgs eventArgs) + { + var textInput = (TextInput)sender; + + CellView realCell = GetRealCell(_cell); + + if (realCell != null) + ((EntryCell)realCell.Cell).Text = textInput.Text; + } + } +} diff --git a/Ooui.Forms/Cells/ImageCellRenderer.cs b/Ooui.Forms/Cells/ImageCellRenderer.cs new file mode 100644 index 0000000..4746c9e --- /dev/null +++ b/Ooui.Forms/Cells/ImageCellRenderer.cs @@ -0,0 +1,66 @@ +using Ooui.Forms.Renderers; +using System.ComponentModel; +using System.Threading.Tasks; +using Xamarin.Forms; +using Xamarin.Forms.Internals; + +namespace Ooui.Forms.Cells +{ + public class ImageCellRenderer : TextCellRenderer + { + public override CellView GetCell(Cell item, CellView reusableView, List listView) + { + var nativeImageCell = reusableView as CellView ?? new CellView(); + + var result = (CellView)base.GetCell(item, nativeImageCell, listView); + + var imageCell = (ImageCell)item; + + WireUpForceUpdateSizeRequested(item, result); + +#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed + SetImage(imageCell, result); +#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed + + return result; + } + + protected override async void HandlePropertyChanged(object sender, PropertyChangedEventArgs args) + { + var tvc = (CellView)sender; + var imageCell = (ImageCell)tvc.Cell; + + base.HandlePropertyChanged(sender, args); + + if (args.PropertyName == ImageCell.ImageSourceProperty.PropertyName) + await SetImage(imageCell, tvc); + } + + static async Task SetImage(ImageCell cell, CellView target) + { + var source = cell.ImageSource; + + target.ImageView.Source = null; + + IImageSourceHandler handler; + + if (source != null && (handler = + Registrar.Registered.GetHandler(source.GetType())) != null) + { + string image; + try + { + image = await handler.LoadImageAsync(source).ConfigureAwait(false); + } + catch (TaskCanceledException) + { + image = null; + } + + target.ImageView.Source = image; + } + else + target.ImageView.Source = null; + } + } +} diff --git a/Ooui.Forms/Cells/SwitchCellRenderer.cs b/Ooui.Forms/Cells/SwitchCellRenderer.cs new file mode 100644 index 0000000..e6e1536 --- /dev/null +++ b/Ooui.Forms/Cells/SwitchCellRenderer.cs @@ -0,0 +1,79 @@ +using System; +using System.ComponentModel; +using Xamarin.Forms; + +namespace Ooui.Forms.Cells +{ + public class SwitchCellRenderer : CellRenderer + { + private static Cell _cell; + + public override CellView GetCell(Cell item, CellView reusableView, List listView) + { + var nativeSwitchCell = reusableView as CellView; + Input oouiSwitch = null; + + if (nativeSwitchCell == null) + nativeSwitchCell = new CellView(); + else + { + oouiSwitch = nativeSwitchCell.CustomView.FirstChild as Input; + + if (oouiSwitch != null) + { + nativeSwitchCell.CustomView.RemoveChild(oouiSwitch); + oouiSwitch.Click -= OnSwitchClick; + } + nativeSwitchCell.Cell.PropertyChanged -= OnCellPropertyChanged; + } + + SetRealCell(item, nativeSwitchCell); + + if (oouiSwitch == null) + { + oouiSwitch = new Input(InputType.Checkbox); + oouiSwitch.SetAttribute("data-toggle", "toggle"); + } + + var switchCell = (SwitchCell)item; + + nativeSwitchCell.Cell = item; + nativeSwitchCell.SecondCol.Style.Width = "25%"; + _cell = nativeSwitchCell.Cell; + + nativeSwitchCell.Cell.PropertyChanged += OnCellPropertyChanged; + nativeSwitchCell.CustomView.AppendChild(oouiSwitch); + nativeSwitchCell.TextLabel.Text = switchCell.Text ?? string.Empty; + + oouiSwitch.IsChecked = switchCell.On; + oouiSwitch.Click += OnSwitchClick; + + WireUpForceUpdateSizeRequested(item, nativeSwitchCell); + + UpdateBackground(nativeSwitchCell, item); + + return nativeSwitchCell; + } + + private void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e) + { + var switchCell = (SwitchCell)sender; + var nativeSwitchCell = (CellView)GetRealCell(switchCell); + + if (e.PropertyName == SwitchCell.OnProperty.PropertyName) + ((Input)nativeSwitchCell.CustomView.FirstChild).IsChecked = switchCell.On; + else if (e.PropertyName == SwitchCell.TextProperty.PropertyName) + nativeSwitchCell.TextLabel.Text = switchCell.Text ?? string.Empty; + } + + private void OnSwitchClick(object sender, EventArgs eventArgs) + { + var switchInput = (Input)sender; + + CellView realCell = GetRealCell(_cell); + + if (realCell != null) + ((SwitchCell)realCell.Cell).On = switchInput.IsChecked; + } + } +} diff --git a/Ooui.Forms/Cells/TextCellRenderer.cs b/Ooui.Forms/Cells/TextCellRenderer.cs new file mode 100644 index 0000000..2e43a9e --- /dev/null +++ b/Ooui.Forms/Cells/TextCellRenderer.cs @@ -0,0 +1,48 @@ +using Ooui.Forms.Extensions; +using System.ComponentModel; +using Xamarin.Forms; + +namespace Ooui.Forms.Cells +{ + public class TextCellRenderer : CellRenderer + { + public override CellView GetCell(Cell item, CellView reusableView, List listView) + { + var nativeTextCell = base.GetCell(item, reusableView, listView); + var textCell = (TextCell)item; + + if (nativeTextCell.Cell != null) + nativeTextCell.Cell.PropertyChanged -= nativeTextCell.HandlePropertyChanged; + + nativeTextCell.Cell = textCell; + textCell.PropertyChanged += nativeTextCell.HandlePropertyChanged; + nativeTextCell.PropertyChanged = HandlePropertyChanged; + + nativeTextCell.TextLabel.Text = textCell.Text ?? string.Empty; + nativeTextCell.DetailTextLabel.Text = textCell.Detail ?? string.Empty; + nativeTextCell.TextLabel.Style.Color = textCell.TextColor.ToOouiColor(); + nativeTextCell.DetailTextLabel.Style.Color = textCell.DetailColor.ToOouiColor(); + + WireUpForceUpdateSizeRequested(item, nativeTextCell); + + UpdateBackground(nativeTextCell, item); + + return nativeTextCell; + } + + protected virtual void HandlePropertyChanged(object sender, PropertyChangedEventArgs args) + { + var tvc = (CellView)sender; + var textCell = (TextCell)tvc.Cell; + + if (args.PropertyName == TextCell.TextProperty.PropertyName) + tvc.TextLabel.Text = textCell.Text ?? string.Empty; + else if (args.PropertyName == TextCell.DetailProperty.PropertyName) + tvc.DetailTextLabel.Text = textCell.Detail ?? string.Empty; + else if (args.PropertyName == TextCell.TextColorProperty.PropertyName) + tvc.TextLabel.Style.Color = textCell.TextColor.ToOouiColor(); + else if (args.PropertyName == TextCell.DetailColorProperty.PropertyName) + tvc.DetailTextLabel.Style.Color = textCell.DetailColor.ToOouiColor(); + } + } +} diff --git a/Ooui.Forms/Cells/ViewCellRenderer.cs b/Ooui.Forms/Cells/ViewCellRenderer.cs new file mode 100644 index 0000000..5fffef1 --- /dev/null +++ b/Ooui.Forms/Cells/ViewCellRenderer.cs @@ -0,0 +1,25 @@ +using Xamarin.Forms; + +namespace Ooui.Forms.Cells +{ + public class ViewCellRenderer : CellRenderer + { + public override CellView GetCell(Cell item, CellView reusableView, List listView) + { + var viewCell = (ViewCell)item; + + var nativeViewCell = reusableView as ViewCellView; + + if (nativeViewCell == null) + nativeViewCell = new ViewCellView(); + + nativeViewCell.ViewCell = viewCell; + + SetRealCell(item, nativeViewCell); + + WireUpForceUpdateSizeRequested(item, nativeViewCell); + + return nativeViewCell; + } + } +} diff --git a/Ooui.Forms/Cells/ViewCellView.cs b/Ooui.Forms/Cells/ViewCellView.cs new file mode 100644 index 0000000..6bec165 --- /dev/null +++ b/Ooui.Forms/Cells/ViewCellView.cs @@ -0,0 +1,63 @@ +using Ooui.Forms.Renderers; +using System; +using Xamarin.Forms; + +namespace Ooui.Forms.Cells +{ + public class ViewCellView : CellView + { + private WeakReference _rendererRef; + private ViewCell _viewCell; + + public ViewCell ViewCell + { + get { return _viewCell; } + set + { + if (_viewCell == value) + return; + UpdateCell(value); + } + } + + private void UpdateCell(ViewCell cell) + { + if (_viewCell != null) + Device.BeginInvokeOnMainThread(_viewCell.SendDisappearing); + + _viewCell = cell; + + Device.BeginInvokeOnMainThread(_viewCell.SendAppearing); + + IVisualElementRenderer renderer; + if (_rendererRef == null || !_rendererRef.TryGetTarget(out renderer)) + renderer = GetNewRenderer(); + else + { + if (renderer.Element != null && renderer == Platform.GetRenderer(renderer.Element)) + renderer.Element.ClearValue(Platform.RendererProperty); + + var type = Xamarin.Forms.Internals.Registrar.Registered.GetHandlerType(_viewCell.View.GetType()); + var reflectableType = renderer as System.Reflection.IReflectableType; + var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : renderer.GetType(); + if (rendererType == type || (renderer is DefaultRenderer && type == null)) + renderer.SetElement(_viewCell.View); + else + { + renderer = GetNewRenderer(); + } + } + + Platform.SetRenderer(_viewCell.View, renderer); + } + + private IVisualElementRenderer GetNewRenderer() + { + var newRenderer = Platform.CreateRenderer(_viewCell.View); + _rendererRef = new WeakReference(newRenderer); + AppendChild(newRenderer.NativeView); + + return newRenderer; + } + } +} diff --git a/Ooui.Forms/Exports.cs b/Ooui.Forms/Exports.cs index 3d16c15..2f096f9 100644 --- a/Ooui.Forms/Exports.cs +++ b/Ooui.Forms/Exports.cs @@ -1,5 +1,6 @@ using System; using Ooui.Forms; +using Ooui.Forms.Cells; using Ooui.Forms.Renderers; using Xamarin.Forms; @@ -15,6 +16,7 @@ using Xamarin.Forms; [assembly: ExportRenderer (typeof (Label), typeof (LabelRenderer))] [assembly: ExportRenderer (typeof (LinkLabel), typeof (LinkLabelRenderer))] [assembly: ExportRenderer (typeof (LinkView), typeof (LinkViewRenderer))] +[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRenderer))] [assembly: ExportRenderer (typeof (ProgressBar), typeof (ProgressBarRenderer))] [assembly: ExportRenderer (typeof (SearchBar), typeof (SearchBarRenderer))] [assembly: ExportRenderer(typeof(Slider), typeof(SliderRenderer))] @@ -23,7 +25,12 @@ using Xamarin.Forms; [assembly: ExportImageSourceHandler (typeof (FileImageSource), typeof (FileImageSourceHandler))] [assembly: ExportImageSourceHandler (typeof (StreamImageSource), typeof (StreamImagesourceHandler))] [assembly: ExportImageSourceHandler (typeof (UriImageSource), typeof (ImageLoaderSourceHandler))] - +[assembly: ExportCell(typeof(Cell), typeof(CellRenderer))] +[assembly: ExportCell(typeof(EntryCell), typeof(EntryCellRenderer))] +[assembly: ExportCell(typeof(ImageCell), typeof(ImageCellRenderer))] +[assembly: ExportCell(typeof(SwitchCell), typeof(SwitchCellRenderer))] +[assembly: ExportCell(typeof(TextCell), typeof(TextCellRenderer))] +[assembly: ExportCell(typeof(ViewCell), typeof(ViewCellRenderer))] namespace Ooui.Forms { [AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true)] @@ -35,6 +42,14 @@ namespace Ooui.Forms } } + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class ExportCellAttribute : HandlerAttribute + { + public ExportCellAttribute(Type handler, Type target) : base(handler, target) + { + } + } + [AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true)] public sealed class ExportImageSourceHandlerAttribute : HandlerAttribute { diff --git a/Ooui.Forms/Forms.cs b/Ooui.Forms/Forms.cs index 94bc20e..bcae580 100644 --- a/Ooui.Forms/Forms.cs +++ b/Ooui.Forms/Forms.cs @@ -30,7 +30,7 @@ namespace Xamarin.Forms Registrar.RegisterAll (new[] { typeof(ExportRendererAttribute), - //typeof(ExportCellAttribute), + typeof(ExportCellAttribute), typeof(ExportImageSourceHandlerAttribute), }); } diff --git a/Ooui.Forms/Renderers/ListViewRenderer.cs b/Ooui.Forms/Renderers/ListViewRenderer.cs new file mode 100644 index 0000000..da198fe --- /dev/null +++ b/Ooui.Forms/Renderers/ListViewRenderer.cs @@ -0,0 +1,112 @@ +using Ooui.Forms.Extensions; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using Xamarin.Forms; +using Xamarin.Forms.Internals; + +namespace Ooui.Forms.Renderers +{ + public class ListViewRenderer : ViewRenderer + { + private bool _disposed; + private List _listView; + private List _cells; + + public ListViewRenderer() + { + _cells = new List(); + } + + ITemplatedItemsView TemplatedItemsView => Element; + + protected override void OnElementChanged(ElementChangedEventArgs e) + { + if (e.NewElement != null) + { + if (Control == null) + { + _listView = new List(); + + SetNativeControl(_listView); + } + + UpdateItems(); + UpdateBackgroundColor(); + } + + base.OnElementChanged(e); + } + + protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) + { + base.OnElementPropertyChanged(sender, e); + + if (e.PropertyName == ListView.ItemsSourceProperty.PropertyName) + UpdateItems(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing && !_disposed) + { + _disposed = true; + } + } + + private void UpdateItems() + { + _cells.Clear(); + + var items = TemplatedItemsView.TemplatedItems; + + if (!items.Any()) + { + return; + } + + bool grouping = Element.IsGroupingEnabled; + + if (grouping) + { + return; + } + + foreach (var item in items) + { + var cell = GetCell(item); + + var listItem = new ListItem(); + listItem.Style["list-style-type"] = "none"; + + listItem.AppendChild(cell); + + _cells.Add(listItem); + } + + foreach (var cell in _cells) + { + _listView.AppendChild(cell); + } + } + + private void UpdateBackgroundColor() + { + var backgroundColor = Element.BackgroundColor.ToOouiColor(); + + _listView.Style.BackgroundColor = backgroundColor; + } + + private Div GetCell(Cell cell) + { + var renderer = + (Cells.CellRenderer)Registrar.Registered.GetHandler(cell.GetType()); + + var realCell = renderer.GetCell(cell, null, _listView); + + return realCell; + } + } +} diff --git a/Samples/ListViewSample.cs b/Samples/ListViewSample.cs new file mode 100644 index 0000000..e76b4e4 --- /dev/null +++ b/Samples/ListViewSample.cs @@ -0,0 +1,136 @@ +using Ooui; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using Xamarin.Forms; + +namespace Samples +{ + public class Light : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + private string _name; + private string _comment; + private Xamarin.Forms.Color _color; + private bool _isOn; + + public string Name { get { return _name; } set { OnPropertyChanged(); _name = value; } } + public string Comment { get { return _comment; } set { OnPropertyChanged(); _comment = value; } } + public Xamarin.Forms.Color Color { get { return _color; } set { OnPropertyChanged(); _color = value; } } + public bool IsOn { get { return _isOn; } set { OnPropertyChanged(); OnPropertyChanged("isNotOn"); _isOn = value; } } + public bool IsNotOn { get { return !_isOn; } } + + public Light() + { + this.IsOn = false; + this.Name = "My first light!"; + this.Color = Xamarin.Forms.Color.Blue; + this.Comment = "Bedroom"; + } + public Light(bool isOn, string name, Xamarin.Forms.Color color, string comment) + { + this.IsOn = isOn; + this.Name = name; + this.Color = color; + this.Comment = comment; + } + void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + public static class DataSource + { + public static ObservableCollection GetLights() + { + ObservableCollection lights = new ObservableCollection() + { + new Light(false, "Bedside", Xamarin.Forms.Color.Blue, "Mel's Bedroom"), + new Light(false, "Desk", Xamarin.Forms.Color.Red, "Mel's Bedroom"), + new Light(true, "Flood Lamp", Xamarin.Forms.Color.Olive, "Outside"), + new Light(false, "hallway1", Xamarin.Forms.Color.Teal, "Entry Hallway"), + new Light(false, "hallway2", Xamarin.Forms.Color.Purple, "Entry Hallway") + }; + + return lights; + } + } + + class EntryListViewSample : ISample + { + public string Title => "Xamarin.Forms Basic Entry ListView Sample"; + + public Ooui.Element CreateElement() + { + var panel = new StackLayout(); + + var titleLabel = new Xamarin.Forms.Label + { + Text = "ListView", + FontSize = 24, + FontAttributes = FontAttributes.Bold + }; + + panel.Children.Add(titleLabel); + + ListView listView = new ListView() { ItemsSource = DataSource.GetLights() }; + + listView.ItemTemplate = new DataTemplate(typeof(EntryCell)); + listView.ItemTemplate.SetBinding(EntryCell.LabelProperty, "Comment"); + listView.ItemTemplate.SetBinding(EntryCell.TextProperty, "Name"); + + panel.Children.Add(listView); + + var page = new ContentPage + { + Content = panel + }; + + return page.GetOouiElement(); + } + + public void Publish() + { + UI.Publish("/entry-listview", CreateElement); + } + } + + class SwitchListViewSample : ISample + { + public string Title => "Xamarin.Forms Basic Switch ListView Sample"; + + public Ooui.Element CreateElement() + { + var panel = new StackLayout(); + + var titleLabel = new Xamarin.Forms.Label + { + Text = "ListView", + FontSize = 24, + FontAttributes = FontAttributes.Bold + }; + + panel.Children.Add(titleLabel); + + ListView listView = new ListView() { ItemsSource = DataSource.GetLights() }; + + listView.ItemTemplate = new DataTemplate(typeof(SwitchCell)); + listView.ItemTemplate.SetBinding(SwitchCell.TextProperty, "Name"); + listView.ItemTemplate.SetBinding(SwitchCell.OnProperty, "IsOn"); + + panel.Children.Add(listView); + + var page = new ContentPage + { + Content = panel + }; + + return page.GetOouiElement(); + } + + public void Publish() + { + UI.Publish("/switch-listview", CreateElement); + } + } +} diff --git a/Samples/Monkeys/Images/Baboon.jpg b/Samples/Monkeys/Images/Baboon.jpg new file mode 100644 index 0000000..397559e Binary files /dev/null and b/Samples/Monkeys/Images/Baboon.jpg differ diff --git a/Samples/Monkeys/Images/BlueMonkey.jpg b/Samples/Monkeys/Images/BlueMonkey.jpg new file mode 100644 index 0000000..87fa368 Binary files /dev/null and b/Samples/Monkeys/Images/BlueMonkey.jpg differ diff --git a/Samples/Monkeys/Images/Capuchin.jpg b/Samples/Monkeys/Images/Capuchin.jpg new file mode 100644 index 0000000..ca72719 Binary files /dev/null and b/Samples/Monkeys/Images/Capuchin.jpg differ diff --git a/Samples/Monkeys/Images/GoldenLionTamarin.jpg b/Samples/Monkeys/Images/GoldenLionTamarin.jpg new file mode 100644 index 0000000..af048d6 Binary files /dev/null and b/Samples/Monkeys/Images/GoldenLionTamarin.jpg differ diff --git a/Samples/Monkeys/Images/Howler.jpg b/Samples/Monkeys/Images/Howler.jpg new file mode 100644 index 0000000..19afb3a Binary files /dev/null and b/Samples/Monkeys/Images/Howler.jpg differ diff --git a/Samples/Monkeys/Images/Squirrel.jpg b/Samples/Monkeys/Images/Squirrel.jpg new file mode 100644 index 0000000..d81fbe1 Binary files /dev/null and b/Samples/Monkeys/Images/Squirrel.jpg differ diff --git a/Samples/Monkeys/Monkey.cs b/Samples/Monkeys/Monkey.cs new file mode 100644 index 0000000..c5c7729 --- /dev/null +++ b/Samples/Monkeys/Monkey.cs @@ -0,0 +1,13 @@ +using Xamarin.Forms; + +namespace Monkeys.Models +{ + public class Monkey + { + public string Name { get; set; } + public string Location { get; set; } + public string Details { get; set; } + public ImageSource Image { get; set; } + } +} + diff --git a/Samples/Monkeys/MonkeyHelper.cs b/Samples/Monkeys/MonkeyHelper.cs new file mode 100644 index 0000000..74a733b --- /dev/null +++ b/Samples/Monkeys/MonkeyHelper.cs @@ -0,0 +1,60 @@ +using System.Collections.ObjectModel; +using Monkeys.Models; +using Xamarin.Forms; + +namespace Monkeys.Helpers +{ + public static class MonkeyHelper + { + public static ObservableCollection Monkeys { get; set; } + + static MonkeyHelper() + { + Monkeys = new ObservableCollection + { + new Monkey + { + Name = "Baboon", + Location = "Africa & Asia", + Details = "Baboons are African and Arabian Old World monkeys belonging to the genus Papio, part of the subfamily Cercopithecinae.", + Image = ImageSource.FromResource("Samples.Monkeys.Images.Baboon.jpg", System.Reflection.Assembly.GetCallingAssembly()) + }, + new Monkey + { + Name = "Capuchin Monkey", + Location = "Central & South America", + Details = "The capuchin monkeys are New World monkeys of the subfamily Cebinae. Prior to 2011, the subfamily contained only a single genus, Cebus.", + Image = ImageSource.FromResource("Samples.Monkeys.Images.Capuchin.jpg", System.Reflection.Assembly.GetCallingAssembly()) + }, + new Monkey + { + Name = "Blue Monkey", + Location = "Central and East Africa", + Details = "The blue monkey or diademed monkey is a species of Old World monkey native to Central and East Africa, ranging from the upper Congo River basin east to the East African Rift and south to northern Angola and Zambia", + Image = ImageSource.FromResource("Samples.Monkeys.Images.BlueMonkey.jpg", System.Reflection.Assembly.GetCallingAssembly()) + }, + new Monkey + { + Name = "Squirrel Monkey", + Location = "Central & South America", + Details = "The squirrel monkeys are the New World monkeys of the genus Saimiri. They are the only genus in the subfamily Saimirinae. The name of the genus Saimiri is of Tupi origin, and was also used as an English name by early researchers.", + Image = ImageSource.FromResource("Samples.Monkeys.Images.Squirrel.jpg", System.Reflection.Assembly.GetCallingAssembly()) + }, + new Monkey + { + Name = "Golden Lion Tamarin", + Location = "Brazil", + Details = "The golden lion tamarin also known as the golden marmoset, is a small New World monkey of the family Callitrichidae.", + Image = ImageSource.FromResource("Samples.Monkeys.Images.GoldenLionTamarin.jpg", System.Reflection.Assembly.GetCallingAssembly()) + }, + new Monkey + { + Name = "Howler Monkey", + Location = "South America", + Details = "Howler monkeys are among the largest of the New World monkeys. Fifteen species are currently recognised. Previously classified in the family Cebidae, they are now placed in the family Atelidae.", + Image = ImageSource.FromResource("Samples.Monkeys.Images.Howler.jpg", System.Reflection.Assembly.GetCallingAssembly()) + } + }; + } + } +} diff --git a/Samples/Monkeys/MonkeysView.xaml b/Samples/Monkeys/MonkeysView.xaml new file mode 100644 index 0000000..e78737b --- /dev/null +++ b/Samples/Monkeys/MonkeysView.xaml @@ -0,0 +1,54 @@ + + + + + + + diff --git a/Samples/Monkeys/MonkeysView.xaml.cs b/Samples/Monkeys/MonkeysView.xaml.cs new file mode 100644 index 0000000..c9eefd6 --- /dev/null +++ b/Samples/Monkeys/MonkeysView.xaml.cs @@ -0,0 +1,15 @@ +using Monkeys.ViewModels; +using Xamarin.Forms; + +namespace Monkeys.Views +{ + public partial class MonkeysView : ContentPage + { + public MonkeysView() + { + InitializeComponent(); + + BindingContext = new MonkeysViewModel(); + } + } +} diff --git a/Samples/Monkeys/MonkeysViewModel.cs b/Samples/Monkeys/MonkeysViewModel.cs new file mode 100644 index 0000000..bbbb09a --- /dev/null +++ b/Samples/Monkeys/MonkeysViewModel.cs @@ -0,0 +1,16 @@ +using Monkeys.Helpers; +using Monkeys.Models; +using System.Collections.ObjectModel; + +namespace Monkeys.ViewModels +{ + public class MonkeysViewModel + { + public ObservableCollection Monkeys { get; set; } + + public MonkeysViewModel() + { + Monkeys = MonkeyHelper.Monkeys; + } + } +} diff --git a/Samples/MonkeysSample.cs b/Samples/MonkeysSample.cs new file mode 100644 index 0000000..ea7b23a --- /dev/null +++ b/Samples/MonkeysSample.cs @@ -0,0 +1,24 @@ +using Ooui; +using System; +using System.Collections.Generic; +using System.Text; +using Xamarin.Forms; + +namespace Samples +{ + public class MonkeysSample : ISample + { + public string Title => "Xamarin.Forms Monkeys"; + + public Ooui.Element CreateElement() + { + var page = new Monkeys.Views.MonkeysView(); + return page.GetOouiElement(); + } + + public void Publish() + { + UI.Publish("/monkeys", CreateElement); + } + } +} diff --git a/Samples/Program.cs b/Samples/Program.cs index 1c7466d..13921dc 100644 --- a/Samples/Program.cs +++ b/Samples/Program.cs @@ -25,6 +25,7 @@ namespace Samples } } + new EntryListViewSample().Publish(); new ButtonSample ().Publish (); new TodoSample ().Publish (); new DrawSample ().Publish (); @@ -32,8 +33,10 @@ namespace Samples new DisplayAlertSample ().Publish (); new DotMatrixClockSample().Publish(); new EditorSample().Publish(); + new MonkeysSample().Publish(); new SearchBarSample().Publish(); new SliderSample().Publish(); + new SwitchListViewSample().Publish(); new TimePickerSample().Publish(); new TipCalcSample().Publish(); new WeatherAppSample().Publish(); diff --git a/Samples/Samples.csproj b/Samples/Samples.csproj index bdbc539..3ba2b0d 100644 --- a/Samples/Samples.csproj +++ b/Samples/Samples.csproj @@ -17,6 +17,12 @@ + + + + + + @@ -41,6 +47,9 @@ MSBuild:Compile + + MSBuild:Compile + MSBuild:Compile @@ -56,6 +65,13 @@ + + + + + + +