Skip to content

Instantly share code, notes, and snippets.

@slodge
Created June 28, 2012 15:23
Show Gist options
  • Save slodge/3011980 to your computer and use it in GitHub Desktop.
Save slodge/3011980 to your computer and use it in GitHub Desktop.
Change MvxBindableListAdapterWithChangedEvent to pass on NotifyCollectionChangedEventArgs
#region Copyright
// <copyright file="MvxBindableListAdapter.cs" company="Cirrious">
// (c) Copyright Cirrious. http://www.cirrious.com
// This source is subject to the Microsoft Public License (Ms-PL)
// Please see license.txt on http://opensource.org/licenses/ms-pl.html
// All other rights reserved.
// </copyright>
//
// Project Lead - Stuart Lodge, Cirrious. http://www.cirrious.com
#endregion
using System.Collections;
using System.Collections.Specialized;
using Android;
using Android.Content;
using Android.Views;
using Android.Widget;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Views;
using Cirrious.MvvmCross.Exceptions;
using Cirrious.MvvmCross.Interfaces.Platform.Diagnostics;
using Java.Lang;
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public class MvxBindableListAdapter
: BaseAdapter
{
private readonly IMvxBindingActivity _bindingActivity;
private readonly Context _context;
private int _itemTemplateId;
private IList _itemsSource;
public MvxBindableListAdapter(Context context)
{
_context = context;
_bindingActivity = context as IMvxBindingActivity;
if (_bindingActivity == null)
throw new MvxException("MvxBindableListView can only be used within a Context which supports IMvxBindingActivity");
}
protected Context Context { get { return _context; } }
protected IMvxBindingActivity BindingActivity { get { return _bindingActivity; } }
public IList ItemsSource
{
get { return _itemsSource; }
set {
SetItemsSource(value);
}
}
public int ItemTemplateId
{
get { return _itemTemplateId; }
set
{
if (_itemTemplateId == value)
return;
_itemTemplateId = value;
// since the template has changed then let's force the list to redisplay by firing NotifyDataSetChanged()
if (_itemsSource != null)
NotifyDataSetChanged();
}
}
public override int Count
{
get
{
if (_itemsSource == null)
return 0;
return _itemsSource.Count;
}
}
protected virtual void SetItemsSource(IList value)
{
if (_itemsSource == value)
return;
var existingObservable = _itemsSource as INotifyCollectionChanged;
if (existingObservable != null)
existingObservable.CollectionChanged -= OnItemsSourceCollectionChanged;
_itemsSource = value;
var newObservable = _itemsSource as INotifyCollectionChanged;
if (newObservable != null)
newObservable.CollectionChanged += OnItemsSourceCollectionChanged;
NotifyDataSetChanged();
}
private void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
NotifyDataSetChanged(e);
}
protected virtual void NotifyDataSetChanged(NotifyCollectionChangedEventArgs e)
{
base.NotifyDataSetChanged();
}
public override Object GetItem(int position)
{
if (_itemsSource == null)
return null;
return new MvxJavaContainer<object>(_itemsSource[position]);
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
if (_itemsSource == null)
{
MvxBindingTrace.Trace(MvxTraceLevel.Error, "GetView called when ItemsSource is null");
return null;
}
if (position < 0 || position >= _itemsSource.Count)
{
MvxBindingTrace.Trace(MvxTraceLevel.Error, "GetView called with invalid Position - zero indexed {0} out of {1}", position, _itemsSource.Count);
return null;
}
var source = _itemsSource[position];
return GetBindableView(convertView, source);
}
protected virtual View GetSimpleView(View convertView, object source)
{
if (convertView == null)
{
convertView = CreateSimpleView(source);
}
else
{
BindSimpleView(convertView, source);
}
return convertView;
}
protected virtual void BindSimpleView(View convertView, object source)
{
var textView = convertView as TextView;
if (textView != null)
{
textView.Text = (source ?? string.Empty).ToString();
}
}
protected virtual View CreateSimpleView(object source)
{
var view = _bindingActivity.NonBindingInflate(Resource.Layout.SimpleListItem1, null);
BindSimpleView(view, source);
return view;
}
protected virtual View GetBindableView(View convertView, object source)
{
return GetBindableView(convertView, source, ItemTemplateId);
}
protected virtual View GetBindableView(View convertView, object source, int templateId)
{
if (templateId == 0)
{
// no template seen - so use a standard string view from Android and use ToString()
return GetSimpleView(convertView, source);
}
// we have a templateid so lets use bind and inflate on it :)
var viewToUse = convertView as IMvxBindableListItemView;
if (viewToUse != null)
{
if (viewToUse.TemplateId != templateId)
{
viewToUse = null;
}
}
if (viewToUse == null)
{
viewToUse = CreateBindableView(source, templateId);
}
else
{
BindBindableView(source, viewToUse);
}
return viewToUse as View;
}
protected virtual void BindBindableView(object source, IMvxBindableListItemView viewToUse)
{
viewToUse.BindTo(source);
}
protected virtual MvxBindableListItemView CreateBindableView(object source, int templateId)
{
return new MvxBindableListItemView(_context, _bindingActivity, templateId, source);
}
}
}
#region Copyright
// <copyright file="MvxBindableListAdapterWithChangedEvent.cs" company="Cirrious">
// (c) Copyright Cirrious. http://www.cirrious.com
// This source is subject to the Microsoft Public License (Ms-PL)
// Please see license.txt on http://opensource.org/licenses/ms-pl.html
// All other rights reserved.
// </copyright>
//
// Project Lead - Stuart Lodge, Cirrious. http://www.cirrious.com
#endregion
using System;
using System.Collections.Specialized;
using Android.Content;
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public class MvxBindableListAdapterWithChangedEvent
: MvxBindableListAdapter
{
public MvxBindableListAdapterWithChangedEvent(Context context)
: base(context)
{
}
public event EventHandler<NotifyCollectionChangedEventArgs> DataSetChanged;
public override void NotifyDataSetChanged()
{
this.NotifyDataSetChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
protected override void NotifyDataSetChanged(NotifyCollectionChangedEventArgs e)
{
base.NotifyDataSetChanged(e);
var handler = DataSetChanged;
if (handler != null)
handler(this, e);
}
}
}
#region Copyright
// <copyright file="MvxBindableLinearLayout.cs" company="Cirrious">
// (c) Copyright Cirrious. http://www.cirrious.com
// This source is subject to the Microsoft Public License (Ms-PL)
// Please see license.txt on http://opensource.org/licenses/ms-pl.html
// All other rights reserved.
// </copyright>
//
// Project Lead - Stuart Lodge, Cirrious. http://www.cirrious.com
#endregion
using System;
using System.Collections;
using System.Collections.Specialized;
using Android.Content;
using Android.Util;
using Android.Widget;
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public static class MvxBindableLinearLayoutExtensions
{
public static void Refill(this LinearLayout layout, IAdapter adapter)
{
layout.RemoveAllViews();
var count = adapter.Count;
for (var i = 0; i < count; i++)
{
layout.AddView(adapter.GetView(i, null, layout));
}
}
}
public class MvxBindableLinearLayout
: LinearLayout
{
public MvxBindableLinearLayout(Context context, IAttributeSet attrs)
: base(context, attrs)
{
var itemTemplateId = MvxBindableListViewHelpers.ReadTemplatePath(context, attrs);
Adapter = new MvxBindableListAdapterWithChangedEvent(context);
Adapter.ItemTemplateId = itemTemplateId;
Adapter.DataSetChanged += AdapterOnDataSetChanged;
this.ChildViewRemoved += OnChildViewRemoved;
}
private void OnChildViewRemoved(object sender, ChildViewRemovedEventArgs childViewRemovedEventArgs)
{
var boundChild = childViewRemovedEventArgs.Child as MvxBindableListItemView;
if (boundChild != null)
{
boundChild.ClearBindings();
}
}
public MvxBindableListAdapterWithChangedEvent Adapter { get; set; }
public IList ItemsSource
{
get { return Adapter.ItemsSource; }
set { Adapter.ItemsSource = value; }
}
public int ItemTemplateId
{
get { return Adapter.ItemTemplateId; }
set { Adapter.ItemTemplateId = value; }
}
private void AdapterOnDataSetChanged(object sender, NotifyCollectionChangedEventArgs eventArgs)
{
// TODO - instead of just Refill, use the eventArgs here... like in code in Issue
this.Refill(Adapter);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment