summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.WinRT/CarouselViewRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.WinRT/CarouselViewRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.WinRT/CarouselViewRenderer.cs220
1 files changed, 220 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.WinRT/CarouselViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/CarouselViewRenderer.cs
new file mode 100644
index 00000000..3e1fd096
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/CarouselViewRenderer.cs
@@ -0,0 +1,220 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using WFlipView = Windows.UI.Xaml.Controls.FlipView;
+using WBinding = Windows.UI.Xaml.Data.Binding;
+using WApp = Windows.UI.Xaml.Application;
+using WSize = Windows.Foundation.Size;
+using WDataTemplate = Windows.UI.Xaml.DataTemplate;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class CarouselViewRenderer : ViewRenderer<CarouselView, FrameworkElement>
+ {
+ WFlipView _flipView;
+
+ bool _leftAdd;
+
+ ICarouselViewController Controller
+ {
+ get { return Element; }
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<CarouselView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ _flipView.SelectionChanged -= SelectionChanged;
+ _flipView.ItemsSource = null;
+ Element.CollectionChanged -= CollectionChanged;
+ }
+
+ if (e.NewElement != null)
+ {
+ if (_flipView == null)
+ {
+ _flipView = new FlipView { IsSynchronizedWithCurrentItem = false, ItemTemplate = (WDataTemplate)WApp.Current.Resources["ItemTemplate"] };
+ }
+
+ _flipView.ItemsSource = Element.ItemsSource;
+ _flipView.SelectedIndex = Element.Position;
+ _flipView.SelectionChanged += SelectionChanged;
+ Element.CollectionChanged += CollectionChanged;
+ }
+
+ if (_flipView != Control)
+ SetNativeControl(_flipView);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Position" && _flipView.SelectedIndex != Element.Position)
+ {
+ if (!_leftAdd)
+ _flipView.SelectedIndex = Element.Position;
+ _leftAdd = false;
+ }
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ Controller.SendSelectedPositionChanged(_flipView.SelectedIndex);
+
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (e.NewStartingIndex <= Element.Position)
+ {
+ _leftAdd = true;
+ int position = Element.Position + e.NewItems.Count;
+ PositionChanged(position);
+ }
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ if (Element.Count == 0)
+ throw new InvalidOperationException("CarouselView must retain a least one item.");
+
+ if (e.OldStartingIndex < Element.Position)
+ PositionChanged(Element.Position - e.OldItems.Count);
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ break;
+
+ case NotifyCollectionChangedAction.Reset:
+ break;
+
+ default:
+ throw new Exception($"Enum value '{(int)e.Action}' is not a member of NotifyCollectionChangedAction enumeration.");
+ }
+ }
+
+ void PositionChanged(int position)
+ {
+ if (!_leftAdd)
+ _flipView.SelectedIndex = position;
+ Element.Position = position;
+ Controller.SendSelectedPositionChanged(position);
+ }
+
+ void SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ object[] addedItems = e.AddedItems.ToArray();
+ object[] removedItems = e.RemovedItems.ToArray();
+
+ object addedItem = addedItems.SingleOrDefault();
+ if (addedItem != null)
+ {
+ PositionChanged(_flipView.SelectedIndex);
+ Controller.SendSelectedItemChanged(addedItems.Single());
+ }
+ }
+ }
+
+ public class ItemControl : ContentControl
+ {
+ CarouselView _carouselView;
+ object _item;
+ View _view;
+
+ public ItemControl()
+ {
+ DataContextChanged += OnDataContextChanged;
+ }
+
+ CarouselView CarouselView => LoadCarouselView();
+
+ IItemViewController Controller => CarouselView;
+
+ protected override WSize ArrangeOverride(WSize finalSize)
+ {
+ _view.Layout(new Rectangle(0, 0, CarouselView.Width, CarouselView.Height));
+ return base.ArrangeOverride(finalSize);
+ }
+
+ protected override WSize MeasureOverride(WSize availableSize)
+ {
+ LoadCarouselView();
+
+ if (_item != null)
+ {
+ SetDataContext(_item);
+ _item = null;
+ }
+
+ return base.MeasureOverride(availableSize);
+ }
+
+ CarouselView LoadCarouselView()
+ {
+ if (_carouselView != null)
+ return _carouselView;
+
+ DependencyObject parent = VisualTreeHelper.GetParent(this);
+ CarouselViewRenderer renderer = default(CarouselViewRenderer);
+
+ do
+ {
+ if (parent == null)
+ return null;
+
+ renderer = parent as CarouselViewRenderer;
+ if (renderer != null)
+ break;
+
+ parent = VisualTreeHelper.GetParent(parent);
+ } while (true);
+
+ _carouselView = renderer.Element;
+ return _carouselView;
+ }
+
+ void OnDataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
+ {
+ object item = args.NewValue;
+
+ if (_carouselView != null)
+ SetDataContext(item);
+
+ else if (item != null)
+ _item = item;
+ }
+
+ void SetDataContext(object item)
+ {
+ // type item
+ object type = Controller.GetItemType(item);
+
+ // activate item
+ _view = Controller.CreateView(type);
+ _view.Parent = CarouselView;
+ _view.Layout(new Rectangle(0, 0, CarouselView.Width, CarouselView.Height));
+
+ // render item
+ IVisualElementRenderer renderer = Platform.CreateRenderer(_view);
+ Platform.SetRenderer(_view, renderer);
+ Content = renderer;
+
+ // bind item
+ Controller.BindView(_view, item);
+ }
+ }
+} \ No newline at end of file