Last active
April 21, 2020 21:43
-
-
Save nmilcoff/1bab04c2c07f9530244020b5dbde988e to your computer and use it in GitHub Desktop.
iOS MvxStackView (based on https://github.com/Springham/MvvmCross.StackView)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Collections.Specialized; | |
using MvvmCross.Binding.Attributes; | |
using MvvmCross.Core.ViewModels; | |
using MvvmCross.Platform.WeakSubscription; | |
using UIKit; | |
namespace MvvmCross.StackView | |
{ | |
public class MvxStackView<TView> : OAStackView.OAStackView | |
where TView : MvxView, new() | |
{ | |
private IEnumerable<MvxNavigatingObject> itemsSource; | |
private MvxNotifyCollectionChangedEventSubscription subscription; | |
private IDictionary<MvxNavigatingObject, TView> itemsToViewsDictionary; | |
public MvxStackView(UILayoutConstraintAxis axis, float spacing) | |
{ | |
this.Initialize(axis, spacing); | |
} | |
public MvxStackView(IntPtr handler) | |
: base(handler) | |
{ | |
} | |
[MvxSetToNullAfterBinding] | |
public virtual IEnumerable<MvxNavigatingObject> ItemsSource | |
{ | |
get { return this.itemsSource; } | |
set | |
{ | |
if(ReferenceEquals(this.itemsSource, value)) | |
return; | |
this.itemsSource = value; | |
var collectionChanged = this.itemsSource as INotifyCollectionChanged; | |
if(collectionChanged != null) | |
this.subscription = collectionChanged.WeakSubscribe(OnCollectionChanged); | |
InitializeContainer(); | |
} | |
} | |
private void Initialize(UILayoutConstraintAxis axis, float spacing) | |
{ | |
this.Axis = axis; | |
this.Spacing = spacing; | |
this.itemsToViewsDictionary = new Dictionary<MvxNavigatingObject, TView>(); | |
} | |
protected override void Dispose(bool disposing) | |
{ | |
if(disposing) | |
{ | |
if(this.subscription != null) | |
{ | |
this.subscription.Dispose(); | |
this.subscription = null; | |
} | |
} | |
base.Dispose(disposing); | |
} | |
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) | |
{ | |
var newItems = notifyCollectionChangedEventArgs?.NewItems; | |
if(newItems != null) | |
{ | |
var newStartingIndex = notifyCollectionChangedEventArgs.NewStartingIndex; | |
foreach(var newItem in notifyCollectionChangedEventArgs.NewItems) | |
{ | |
this.AddItemToStack(newItem as MvxNavigatingObject, newStartingIndex); | |
newStartingIndex++; | |
} | |
} | |
var oldItems = notifyCollectionChangedEventArgs?.OldItems; | |
if(oldItems != null) | |
{ | |
foreach(var oldItem in notifyCollectionChangedEventArgs.OldItems) | |
this.RemoveItemFromStack(oldItem as MvxNavigatingObject); | |
} | |
} | |
private void InitializeContainer() | |
{ | |
var index = 0; | |
this.itemsToViewsDictionary.Clear(); | |
foreach(var viewModel in ItemsSource) | |
{ | |
this.AddItemToStack(viewModel, index); | |
index++; | |
} | |
} | |
private void AddItemToStack(MvxNavigatingObject item, int index) | |
{ | |
this.InvokeOnMainThread(() => | |
{ | |
if(index == -1) | |
index = 0; | |
var view = new TView(); | |
if(view == null) | |
return; | |
view.DataContext = item; | |
this.itemsToViewsDictionary.Add(item, view); | |
this.OnBeforeAdd(view); | |
this.InsertArrangedSubview(view, (nuint)index); | |
this.OnAfterAdd(view); | |
}); | |
} | |
private void RemoveItemFromStack(MvxNavigatingObject item) | |
{ | |
this.InvokeOnMainThread(() => | |
{ | |
if(!this.itemsToViewsDictionary.ContainsKey(item)) | |
return; | |
var view = this.itemsToViewsDictionary[item]; | |
this.OnBeforeRemove(view); | |
this.RemoveArrangedSubview(view); | |
view.RemoveFromSuperview(); | |
this.itemsToViewsDictionary.Remove(item); | |
this.OnAfterRemove(view); | |
}); | |
} | |
#region lifecycle callbacks | |
protected virtual void OnBeforeAdd(UIView view) | |
{ | |
} | |
protected virtual void OnAfterAdd(UIView view) | |
{ | |
} | |
protected virtual void OnBeforeRemove(UIView view) | |
{ | |
} | |
protected virtual void OnAfterRemove(UIView view) | |
{ | |
} | |
#endregion | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment