Skip to content

Instantly share code, notes, and snippets.

@BitStab
Created May 10, 2012 11:59
Show Gist options
  • Save BitStab/2652614 to your computer and use it in GitHub Desktop.
Save BitStab/2652614 to your computer and use it in GitHub Desktop.
Adapter
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public interface IMvxBindableAutoCompleteTextView
{
int TemplateId { get; }
void BindTo(object source);
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:mobsales="http://schemas.android.com/apk/res/MobSales.DroidUI"
android:id="@+id/dialog_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/txtfield"
android:layout_marginTop="10dp"
android:layout_alignParentTop="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Customer"
android:layout_marginLeft="5dp" />
<ProgressBar
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
mobsales:MvxBind="{'Visibility':{'Path':'IsLoading','Converter':'Visibility'}}"
/>
<cirrious.mvvmcross.binding.android.views.MvxAutoCompleteTextView
android:id="@+id/autocomplete"
android:layout_below="@id/txtfield"
android:layout_centerHorizontal="true"
android:layout_width="fill_parent"
android:layout_marginLeft="5dp"
mobsales:MvxItemTemplate="@layout/listitem_customer"
mobsales:MvxBind="{'ItemsSource':{'Path':'Customers'}}" />
<LinearLayout
android:id="@+id/button_frame"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="80.0dp"
android:layout_below="@id/autocomplete">
<Button
android:text="Select"
android:id="@+id/btnSelect"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<Button
android:text="Cancel"
android:id="@+id/btnCancel"
android:layout_alignRight="@id/btnSelect"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
</RelativeLayout>
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using Android;
using Android.Content;
using Android.Views;
using Android.Widget;
using Android.Runtime;
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 MvxBindableArrayAdapter<T>
: BaseAdapter, IFilterable
{
private readonly IMvxBindingActivity _bindingActivity;
private readonly Context _context;
private Filter _filter;
private int _itemTemplateId;
private IList<T> _itemsSource;
private List<T> _itemsCopy;
public MvxBindableArrayAdapter(Context context)
{
_context = context;
_bindingActivity = context as IMvxBindingActivity;
if (_bindingActivity == null)
throw new MvxException("MvxBindableAutoComleteTextView can only be used within a Context which supports IMvxBindingActivity");
}
protected Context Context { get { return _context; } }
protected IMvxBindingActivity BindingActivity { get { return _bindingActivity; } }
public IList<T> ItemsSource
{
get { return _itemsSource; }
set
{
SetItemsSource(value);
SetItemsCopy(_itemsSource);
}
}
public List<T> ItemsOriginal
{
get { return _itemsCopy; }
set
{
SetItemsCopy(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<T> 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();
}
protected virtual void SetItemsCopy(IList<T> value)
{
if (_itemsCopy == value)
return;
var existingObservable = _itemsCopy as INotifyCollectionChanged;
if (existingObservable != null)
existingObservable.CollectionChanged -= OnItemsSourceCollectionChanged;
foreach (var item in value)
{
_itemsCopy.Add(item);
}
var newObservable = _itemsCopy as INotifyCollectionChanged;
if (newObservable != null)
newObservable.CollectionChanged += OnItemsSourceCollectionChanged;
NotifyDataSetChanged();
}
private void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
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);
}
public override void NotifyDataSetChanged()
{
base.NotifyDataSetChanged();
}
public Filter Filter
{
get
{
if (_filter == null)
{
_filter = new MvxBindableArrayAdapterFilter<T>(this);
return _filter;
}
else
return _filter;
}
}
public void Clear()
{
_itemsSource.Clear();
}
public void Add(T o)
{
_itemsSource.Add(o);
}
}
public class MvxBindableArrayAdapterFilter<T> : Filter
{
MvxBindableArrayAdapter<T> adapter;
public MvxBindableArrayAdapterFilter(MvxBindableArrayAdapter<T> _adapter)
{
adapter = _adapter;
}
protected override void PublishResults(Java.Lang.ICharSequence constraint, Filter.FilterResults results)
{
var getThem = results.Values as IList<T>;
// Clone items so they are local.
List<T> localItems = new List<T>();
foreach (var item in getThem)
{
localItems.Add(item);
}
adapter.NotifyDataSetChanged();
adapter.Clear();
foreach (var item in localItems)
{
adapter.Add(item);
}
}
protected override FilterResults PerformFiltering(Java.Lang.ICharSequence prefix)
{
Converters.MvxLanguageBinderConverter converter = new Converters.MvxLanguageBinderConverter();
List<T> filtered;
if (prefix != null)
{
List<T> result = new List<T>();
foreach (var item in adapter.ItemsSource)
{
string searchable = item.ToString();
if (searchable.ToLowerInvariant().StartsWith(prefix.ToString().ToLowerInvariant()))
result.Add(item);
else
{
string value = searchable.ToLowerInvariant();
string[] valueSplit = value.Split(' ');
foreach (var word in valueSplit)
{
if (word.StartsWith(prefix.ToString().ToLowerInvariant()))
result.Add(item);
}
}
}
filtered = result;
}
else
{
filtered = adapter.ItemsOriginal;
}
JavaList list = new JavaList();
foreach (var item in filtered)
{
list.Add(item as object);
}
FilterResults results = new FilterResults();
results.Values = list;
results.Count = filtered.Count;
return results;
}
}
}
using System.Collections.Generic;
using Android.Content;
using Android.Views;
using Android.Widget;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Views;
using Cirrious.MvvmCross.Binding.Interfaces;
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public class MvxBindableArrayItemView
: FrameLayout
, IMvxBindableListItemView
{
private readonly View _content;
private readonly int _templateId;
public MvxBindableArrayItemView(Context context, IMvxBindingActivity bindingActivity, int templateId, object source)
: base(context)
{
_templateId = templateId;
_content = bindingActivity.BindingInflate(source, templateId, this);
}
protected View Content { get { return _content; } }
#region IMvxBindableListItemView Members
public int TemplateId
{
get { return _templateId; }
}
public virtual void BindTo(object source)
{
if (_content == null)
return;
var tag = _content.GetTag(MvxAndroidBindingResource.Instance.BindingTagUnique);
if (tag == null)
return;
var cast = tag as MvxJavaContainer<Dictionary<View, IList<IMvxUpdateableBinding>>>;
if (cast == null)
return;
foreach (var binding in cast.Object)
{
foreach (var bind in binding.Value)
{
bind.DataContext = source;
}
}
}
#endregion
}
}
using System.Collections;
using System.Collections.Generic;
using Android.Content;
using Android.Util;
using Android.Widget;
using Cirrious.MvvmCross.Interfaces.Commands;
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public class MvxBindableAutoCompleteTextView<T>
: AutoCompleteTextView
{
public MvxBindableAutoCompleteTextView(Context context, IAttributeSet attrs)
: this(context, attrs, new MvxBindableArrayAdapter<T>(context))
{
}
public MvxBindableAutoCompleteTextView(Context context, IAttributeSet attrs, MvxBindableArrayAdapter<T> adapter)
: base(context, attrs)
{
var itemTemplateId = MvxBindableListViewHelpers.ReadTemplatePath(context, attrs);
adapter.ItemTemplateId = itemTemplateId;
Adapter = adapter;
SetupItemClickListener();
}
public new MvxBindableArrayAdapter<T> Adapter
{
get { return base.Adapter as MvxBindableArrayAdapter<T>; }
set
{
var existing = Adapter;
if (existing == value)
return;
if (existing != null && value != null)
{
value.ItemsSource = existing.ItemsSource;
value.ItemTemplateId = existing.ItemTemplateId;
}
base.Adapter = value;
}
}
public IList<T> ItemsSource
{
get { return Adapter.ItemsSource; }
set { Adapter.ItemsSource = value; }
}
public int ItemTemplateId
{
get { return Adapter.ItemTemplateId; }
set { Adapter.ItemTemplateId = value; }
}
public new IMvxCommand ItemClick { get; set; }
private void SetupItemClickListener()
{
base.ItemClick += (sender, args) =>
{
if (this.ItemClick == null)
return;
var item = Adapter.GetItem(args.Position) as MvxJavaContainer;
if (item == null)
return;
if (item.Object == null)
return;
if (!this.ItemClick.CanExecute(item.Object))
return;
this.ItemClick.Execute(item.Object);
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment