diff options
Diffstat (limited to 'Xamarin.Forms.Core/Cells/Cell.cs')
-rw-r--r-- | Xamarin.Forms.Core/Cells/Cell.cs | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/Cells/Cell.cs b/Xamarin.Forms.Core/Cells/Cell.cs new file mode 100644 index 00000000..3b16d06a --- /dev/null +++ b/Xamarin.Forms.Core/Cells/Cell.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace Xamarin.Forms +{ + public abstract class Cell : Element + { + public static readonly BindableProperty IsEnabledProperty = BindableProperty.Create("IsEnabled", typeof(bool), typeof(Cell), true, propertyChanged: OnIsEnabledPropertyChanged); + + ObservableCollection<MenuItem> _contextActions; + + double _height = -1; + + bool _nextCallToForceUpdateSizeQueued; + + public IList<MenuItem> ContextActions + { + get + { + if (_contextActions == null) + { + _contextActions = new ObservableCollection<MenuItem>(); + _contextActions.CollectionChanged += OnContextActionsChanged; + } + + return _contextActions; + } + } + + public bool HasContextActions + { + get { return _contextActions != null && _contextActions.Count > 0 && IsEnabled; } + } + + public double Height + { + get { return _height; } + set + { + if (_height == value) + return; + + OnPropertyChanging("Height"); + OnPropertyChanging("RenderHeight"); + _height = value; + OnPropertyChanged("Height"); + OnPropertyChanged("RenderHeight"); + } + } + + public bool IsEnabled + { + get { return (bool)GetValue(IsEnabledProperty); } + set { SetValue(IsEnabledProperty, value); } + } + + public double RenderHeight + { + get + { + var table = RealParent as TableView; + if (table != null) + return table.HasUnevenRows && Height > 0 ? Height : table.RowHeight; + + var list = RealParent as ListView; + if (list != null) + return list.HasUnevenRows && Height > 0 ? Height : list.RowHeight; + + return 40; + } + } + + public event EventHandler Appearing; + + public event EventHandler Disappearing; + + public void ForceUpdateSize() + { + if (_nextCallToForceUpdateSizeQueued) + return; + + if ((Parent as ListView)?.HasUnevenRows == true) + { + _nextCallToForceUpdateSizeQueued = true; + OnForceUpdateSizeRequested(); + } + } + + public event EventHandler Tapped; + + protected internal virtual void OnTapped() + { + if (Tapped != null) + Tapped(this, EventArgs.Empty); + } + + protected virtual void OnAppearing() + { + EventHandler handler = Appearing; + if (handler != null) + handler(this, EventArgs.Empty); + } + + protected override void OnBindingContextChanged() + { + base.OnBindingContextChanged(); + + if (HasContextActions) + { + for (var i = 0; i < _contextActions.Count; i++) + SetInheritedBindingContext(_contextActions[i], BindingContext); + } + } + + protected virtual void OnDisappearing() + { + EventHandler handler = Disappearing; + if (handler != null) + handler(this, EventArgs.Empty); + } + + protected override void OnParentSet() + { + if (RealParent != null) + { + RealParent.PropertyChanged += OnParentPropertyChanged; + RealParent.PropertyChanging += OnParentPropertyChanging; + } + + base.OnParentSet(); + } + + protected override void OnPropertyChanging(string propertyName = null) + { + if (propertyName == "Parent") + { + if (RealParent != null) + { + RealParent.PropertyChanged -= OnParentPropertyChanged; + RealParent.PropertyChanging -= OnParentPropertyChanging; + } + } + + base.OnPropertyChanging(propertyName); + } + + internal event EventHandler ForceUpdateSizeRequested; + + internal void SendAppearing() + { + OnAppearing(); + + var container = RealParent as IListViewController; + if (container != null) + container.SendCellAppearing(this); + } + + internal void SendDisappearing() + { + OnDisappearing(); + + var container = RealParent as IListViewController; + if (container != null) + container.SendCellDisappearing(this); + } + + void OnContextActionsChanged(object sender, NotifyCollectionChangedEventArgs e) + { + for (var i = 0; i < _contextActions.Count; i++) + SetInheritedBindingContext(_contextActions[i], BindingContext); + + OnPropertyChanged("HasContextActions"); + } + + async void OnForceUpdateSizeRequested() + { + // don't run more than once per 16 milliseconds + await Task.Delay(TimeSpan.FromMilliseconds(16)); + EventHandler handler = ForceUpdateSizeRequested; + if (handler != null) + handler(this, null); + + _nextCallToForceUpdateSizeQueued = false; + } + + static void OnIsEnabledPropertyChanged(BindableObject bindable, object oldvalue, object newvalue) + { + (bindable as Cell).OnPropertyChanged("HasContextActions"); + } + + void OnParentPropertyChanged(object sender, PropertyChangedEventArgs e) + { + // Technically we might be raising this even if it didn't change, but I'm taking the bet that + // its uncommon enough that we don't want to take the penalty of N GetValue calls to verify. + if (e.PropertyName == "RowHeight") + OnPropertyChanged("RenderHeight"); + } + + void OnParentPropertyChanging(object sender, PropertyChangingEventArgs e) + { + if (e.PropertyName == "RowHeight") + OnPropertyChanging("RenderHeight"); + } + } +}
\ No newline at end of file |