Attempt to get GitHub up to date again! Touch not tested through at present

This commit is contained in:
Stuart 2012-02-20 16:42:37 +00:00
Родитель 8441502bc0
Коммит 78a0a236cd
419 изменённых файлов: 615198 добавлений и 2018 удалений

Просмотреть файл

@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Android.Content;
using Android.Util;
using Android.Views;
using Cirrious.MvvmCross.Binding.Android.Binders;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Binders;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using Java.Lang;
using Exception = System.Exception;
namespace Cirrious.MvvmCross.Binding.Android.Binders
{
public class MvxBindingLayoutInflatorFactory
: Java.Lang.Object
, LayoutInflater.IFactory
, IMvxServiceConsumer<IMvxBinder>
, IMvxServiceConsumer<IMvxViewTypeResolver>
{
private readonly object _source;
private readonly LayoutInflater _layoutInflater;
private readonly Dictionary<View, IList<IMvxUpdateableBinding>> _viewBindings
= new Dictionary<View, IList<IMvxUpdateableBinding>>();
private IMvxViewTypeResolver _viewTypeResolver;
private IMvxViewTypeResolver ViewTypeResolver
{
get
{
if (_viewTypeResolver == null)
_viewTypeResolver = this.GetService<IMvxViewTypeResolver>();
return _viewTypeResolver;
}
}
public MvxBindingLayoutInflatorFactory(
object source,
LayoutInflater layoutInflater)
{
_source = source;
_layoutInflater = layoutInflater;
}
public View OnCreateView(string name, Context context, IAttributeSet attrs)
{
View view = CreateView(name, context, attrs);
if (view != null)
{
BindView(view, context, attrs);
}
return view;
}
private void BindView(View view, Context context, IAttributeSet attrs)
{
var typedArray = context.ObtainStyledAttributes(attrs, MvxAndroidBindingResource.Instance.BindingStylableGroupId);
int numStyles = typedArray.IndexCount;
for (var i = 0; i < numStyles; ++i)
{
var attributeId = typedArray.GetIndex(i);
if (attributeId == MvxAndroidBindingResource.Instance.BindingBindId)
{
try
{
var bindingText = typedArray.GetString(attributeId);
var newBindings = this.GetService<IMvxBinder>().Bind(_source, view, bindingText);
if (newBindings != null)
{
var asList = newBindings.ToList();
_viewBindings[view] = asList;
}
}
catch (Exception exception)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error, "Exception thrown during the view binding ", exception.ToLongString());
throw;
}
}
}
typedArray.Recycle();
}
private View CreateView(string name, Context context, IAttributeSet attrs)
{
// resolve the tag name to a type
var viewType = ViewTypeResolver.Resolve(name);
if (viewType == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error, "View type not found - {0}", name);
return null;
}
try
{
var view = Activator.CreateInstance(viewType, context, attrs) as View;
if (view == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error, "Unable to load view {0} from type {1}", name, viewType.FullName);
}
return view;
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error, "Exception during creation of {0} from type {1} - exception", name, viewType.FullName, exception.ToLongString());
return null;
}
}
public void StoreBindings(View view)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Diagnostic, "Storing bindings on {0} views", _viewBindings.Count);
view.SetTag(MvxAndroidBindingResource.Instance.BindingTagUnique, new MvxJavaContainer<Dictionary<View, IList<IMvxUpdateableBinding>>>(_viewBindings));
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
using System.Collections.Generic;
using System.Linq;
using Cirrious.MvvmCross.Binding.Interfaces;
namespace Cirrious.MvvmCross.Binding.Android.Binders
{
public class MvxJavaBindingWrapper : Java.Lang.Object
{
public IList<IMvxUpdateableBinding> Bindings { get; private set; }
public MvxJavaBindingWrapper(IEnumerable<IMvxUpdateableBinding> bindings)
{
Bindings = bindings.ToList();
}
}
}

Просмотреть файл

@ -0,0 +1,37 @@
using System.Collections.Generic;
using Android.Content;
using Android.Util;
using Android.Views;
namespace Cirrious.MvvmCross.Binding.Android.Binders
{
#warning Kill this file!
public class MvxStackingLayoutInflatorFactory
: Java.Lang.Object
, LayoutInflater.IFactory
{
private readonly Stack<LayoutInflater.IFactory> _stack = new Stack<LayoutInflater.IFactory>();
public View OnCreateView(string name, Context context, IAttributeSet attrs)
{
if (_stack.Count == 0)
return null;
var topmost = _stack.Peek();
if (topmost == null)
return null;
return topmost.OnCreateView(name, context, attrs);
}
public void Push(LayoutInflater.IFactory factory)
{
_stack.Push(factory);
}
public LayoutInflater.IFactory Pop()
{
return _stack.Pop();
}
}
}

Просмотреть файл

@ -0,0 +1,42 @@
using System.Reflection;
using System.Text;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Binders;
namespace Cirrious.MvvmCross.Binding.Android.Binders
{
#warning Kill this class
public class MvxViewClassNameResolver : IMvxViewClassNameResolver
{
public virtual string Resolve(string tagName)
{
var nameBuilder = new StringBuilder();
/*
* looking at:
* http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.4_r1/android/view/LayoutInflater.java#LayoutInflater.onCreateView%28java.lang.String%2Candroid.util.AttributeSet%29
if (!IsFullyQualified(tagName))
nameBuilder.Append("android.view.");
*/
switch (tagName)
{
case "View":
case "ViewGroup":
nameBuilder.Append("Android.View.");
break;
default:
if (!IsFullyQualified(tagName))
nameBuilder.Append("Android.Widget.");
break;
}
nameBuilder.Append(tagName);
return nameBuilder.ToString();
}
private static bool IsFullyQualified(string tagName)
{
return tagName.Contains(".");
}
}
}

Просмотреть файл

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.Views;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Binders;
namespace Cirrious.MvvmCross.Binding.Android.Binders
{
public class MvxViewTypeResolver : IMvxViewTypeResolver
{
private Dictionary<string, Type> _cache = new Dictionary<string, Type>();
public virtual Type Resolve(string tagName)
{
var longLowerCaseName = GetLookupName(tagName);
Type toReturn;
if (_cache.TryGetValue(longLowerCaseName, out toReturn))
return toReturn;
var viewType = typeof(View);
#warning AppDomain.CurrentDomain.GetAssemblies is only the loaded assemblies :/
var query = from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
where viewType.IsAssignableFrom(type)
where (type.FullName ?? "-").ToLowerInvariant() == longLowerCaseName
select type;
toReturn = query.FirstOrDefault();
_cache[longLowerCaseName] = toReturn;
return toReturn;
}
protected string GetLookupName(string tagName)
{
var nameBuilder = new StringBuilder();
switch (tagName)
{
case "View":
case "ViewGroup":
nameBuilder.Append("android.view.");
break;
default:
if (!IsFullyQualified(tagName))
nameBuilder.Append("android.widget.");
break;
}
nameBuilder.Append(tagName);
return nameBuilder.ToString().ToLowerInvariant();
}
private static bool IsFullyQualified(string tagName)
{
return tagName.Contains(".");
}
}
}

Просмотреть файл

@ -0,0 +1,54 @@
using System.ComponentModel;
using Android.App;
using Android.Views;
using Android.Widget;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Interfaces.Converters;
using Cirrious.MvvmCross.Interfaces.Localization;
namespace Cirrious.MvvmCross.Binding.Android.ExtensionMethods
{
public static class MvxTextSettingExtensions
{
public static void BindTextViewText(this Activity activity, int targetViewId, INotifyPropertyChanged source, string sourcePropertyName, IMvxValueConverter converter = null, object converterParameter = null)
{
BindTextViewText<string>(activity, targetViewId, source, sourcePropertyName, converter, converterParameter);
}
public static void BindTextViewText<TSourceType>(this Activity activity, int targetViewId, INotifyPropertyChanged source, string sourcePropertyName, IMvxValueConverter converter = null, object converterParameter = null)
{
var description = new MvxBindingDescription()
{
SourcePropertyPath = sourcePropertyName,
Converter = converter,
ConverterParameter = converterParameter,
TargetName = "Text",
Mode = MvxBindingMode.OneWay
};
activity.BindView<TextView>(targetViewId, source, description);
}
public static void SetTextViewText(this Activity activity, int textViewId, IMvxLanguageBinder languageBinder, string key)
{
var textView = activity.FindViewById<TextView>(textViewId);
SetTextViewTextInner(textViewId, textView, languageBinder, key);
}
public static void SetTextViewText(this View view, int textViewId, IMvxLanguageBinder languageBinder, string key)
{
var textView = view.FindViewById<TextView>(textViewId);
SetTextViewTextInner(textViewId, textView, languageBinder, key);
}
private static void SetTextViewTextInner(int textViewId, TextView textView, IMvxLanguageBinder languageBinder, string key)
{
if (textView == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error, "textView not found for binding " + textViewId);
return;
}
textView.Text = languageBinder.GetText(key).Replace("\r", "\n");
}
}
}

Просмотреть файл

@ -0,0 +1,78 @@
using Android.App;
using Android.Views;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.ExtensionMethods;
namespace Cirrious.MvvmCross.Binding.Android.ExtensionMethods
{
public static class MvxViewBindingExtensions
{
private static IMvxBinder Binder
{
get { return MvxServiceProviderExtensions.GetService<IMvxBinder>(); }
}
public static IMvxBinding BindSubViewClickToCommand(this View view, int subViewId, object source, string propertyPath)
{
var subView = view.FindViewById(subViewId);
if (subView == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning,"Problem finding clickable view id " + subViewId);
return null;
}
return subView.BindClickToCommand(source, propertyPath);
}
public static IMvxBinding BindClickToCommand(this View view, object source, string propertyPath)
{
var bindingParameters = new MvxBindingRequest()
{
Source = source,
Target = view,
Description = new MvxBindingDescription()
{
SourcePropertyPath = propertyPath,
TargetName = "Click"
}
};
return Binder.Bind(bindingParameters);
}
public static void BindView<TViewType>
(this Activity activity, int viewId, object source, MvxBindingDescription bindingDescription)
where TViewType : global::Android.Views.View
{
var view = activity.FindViewById<TViewType>(viewId);
if (view == null)
{
MvxBindingTrace.Trace(
MvxBindingTraceLevel.Warning,
"Unable to bind: did not find view {0} of type {1}", viewId, typeof(TViewType));
return;
}
view.Bind(source, bindingDescription);
}
public static IMvxBinding BindSubView(this View view, int targetViewId, object source, MvxBindingDescription bindingDescription)
{
var targetView = view.FindViewById(targetViewId);
if (targetView == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning,
"Unable to bind: did not find view {0}", targetViewId);
return null;
}
return targetView.Bind(source, bindingDescription);
}
public static IMvxBinding Bind(
this View targetView,
object source,
MvxBindingDescription bindingDescription)
{
return Binder.Bind(new MvxBindingRequest(source, targetView, bindingDescription));
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
using System;
using Android.Views;
namespace Cirrious.MvvmCross.Binding.Android.Interfaces.Binders
{
public interface IMvxBindingLayoutInflator : IDisposable
{
View Inflate(int resource, ViewGroup id);
}
}

Просмотреть файл

@ -0,0 +1,8 @@
namespace Cirrious.MvvmCross.Binding.Android.Interfaces.Binders
{
#warning Kill this interface
public interface IMvxViewClassNameResolver
{
string Resolve(string tagName);
}
}

Просмотреть файл

@ -0,0 +1,9 @@
using System;
namespace Cirrious.MvvmCross.Binding.Android.Interfaces.Binders
{
public interface IMvxViewTypeResolver
{
Type Resolve(string tagName);
}
}

Просмотреть файл

@ -0,0 +1,10 @@
using Android.Views;
namespace Cirrious.MvvmCross.Binding.Android.Interfaces.Views
{
public interface IMvxBindingActivity
{
View BindingInflate(object source, int resourceId, ViewGroup viewGroup);
View NonBindingInflate(int resourceId, ViewGroup viewGroup);
}
}

Просмотреть файл

@ -0,0 +1,48 @@
using System;
using System.Reflection;
using Cirrious.MvvmCross.Android.Interfaces;
using Cirrious.MvvmCross.Android.Platform;
using Cirrious.MvvmCross.Exceptions;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
namespace Cirrious.MvvmCross.Binding.Android
{
public class MvxAndroidBindingResource
: IMvxServiceConsumer<IMvxAndroidGlobals>
{
public readonly static MvxAndroidBindingResource Instance = new MvxAndroidBindingResource();
private MvxAndroidBindingResource()
{
var setup = this.GetService();
var resourceTypeName = setup.ExecutableNamespace + ".Resource";
Type resourceType = setup.ExecutableAssembly.GetType(resourceTypeName);
if (resourceType == null)
throw new MvxException("Unable to find resource type - " + resourceTypeName);
try
{
BindingTagUnique = (int)resourceType.GetNestedType("Id").GetField("MvxBindingTagUnique").GetValue(null);
BindingStylableGroupId = (int[])resourceType.GetNestedType("Styleable").GetField("MvxBinding").GetValue(null);
BindingBindId = (int)resourceType.GetNestedType("Styleable").GetField("MvxBinding_MvxBind").GetValue(null);
BindableListViewStylableGroupId = (int[])resourceType.GetNestedType("Styleable").GetField("MvxBindableListView").GetValue(null);
BindableListItemTemplateId = (int)resourceType.GetNestedType("Styleable").GetField("MvxBindableListView_MvxItemTemplate").GetValue(null);
}
catch (Exception exception)
{
throw exception.MvxWrap("Error finding resource ids for MvxBinding - please make sure ResourcesToCopy are linked into the executable");
}
}
public int BindingTagUnique { get; private set; }
public int[] BindingStylableGroupId { get; private set; }
public int BindingBindId { get; private set; }
public int[] BindableListViewStylableGroupId { get; private set; }
public int BindableListItemTemplateId { get; private set; }
}
}

Просмотреть файл

@ -0,0 +1,34 @@
using Android.Widget;
using Cirrious.MvvmCross.Binding.Android.Binders;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Binders;
using Cirrious.MvvmCross.Binding.Android.Target;
using Cirrious.MvvmCross.Binding.Bindings.Source.Construction;
using Cirrious.MvvmCross.Binding.Bindings.Target.Construction;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
namespace Cirrious.MvvmCross.Binding.Android
{
public class MvxAndroidBindingSetup
: MvxBindingSetup
, IMvxServiceProducer<IMvxViewTypeResolver>
{
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxSimplePropertyInfoTargetBindingFactory(typeof(MvxEditTextTextTargetBinding), typeof(EditText), "Text"));
registry.RegisterFactory(new MvxSimplePropertyInfoTargetBindingFactory(typeof(MvxCompoundButtonCheckedTargetBinding), typeof (CompoundButton), "Checked"));
registry.RegisterFactory(new MvxCustomBindingFactory<ImageView>("AssetImagePath", (imageView) => new MvxImageViewDrawableTargetBinding(imageView)));
}
protected override void RegisterPlatformSpecificComponents()
{
base.RegisterPlatformSpecificComponents();
this.RegisterServiceInstance<IMvxViewTypeResolver>(new MvxViewTypeResolver());
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
namespace Cirrious.MvvmCross.Binding.Android
{
public class MvxJavaContainer : Java.Lang.Object
{
public object Object { get; private set; }
public MvxJavaContainer(object theObject)
{
Object = theObject;
}
}
public class MvxJavaContainer<T> : MvxJavaContainer
{
public new T Object { get { return (T)base.Object; } }
public MvxJavaContainer(T theObject)
: base(theObject)
{
}
}
}

Просмотреть файл

@ -0,0 +1,24 @@
using Cirrious.MvvmCross.Android.Interfaces;
using Cirrious.MvvmCross.Android.Platform;
using Cirrious.MvvmCross.Binding.Bindings.Target;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
namespace Cirrious.MvvmCross.Binding.Android.Target
{
public abstract class MvxBaseAndroidTargetBinding
: MvxBaseTargetBinding
, IMvxServiceConsumer<IMvxAndroidGlobals>
{
private IMvxAndroidGlobals _androidGlobals;
protected IMvxAndroidGlobals AndroidGlobals
{
get
{
if (_androidGlobals == null)
_androidGlobals = this.GetService<IMvxAndroidGlobals>();
return _androidGlobals;
}
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
using System.Reflection;
using Android.Widget;
using Cirrious.MvvmCross.Binding.Bindings.Target;
using Cirrious.MvvmCross.Binding.Interfaces;
namespace Cirrious.MvvmCross.Binding.Android.Target
{
public class MvxCompoundButtonCheckedTargetBinding
: MvxPropertyInfoTargetBinding<CompoundButton>
{
public MvxCompoundButtonCheckedTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
var compoundButton = View;
if (compoundButton == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error,
"Error - compoundButton is null in MvxCompoundButtonCheckedTargetBinding");
}
else
{
compoundButton.CheckedChange += CompoundButtonOnCheckedChange;
}
}
private void CompoundButtonOnCheckedChange(object sender, CompoundButton.CheckedChangeEventArgs args)
{
FireValueChanged(View.Checked);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var compoundButton = View;
if (compoundButton != null)
{
compoundButton.CheckedChange -= CompoundButtonOnCheckedChange;
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,51 @@
using System.Reflection;
using Android.Text;
using Android.Widget;
using Cirrious.MvvmCross.Binding.Bindings.Target;
using Cirrious.MvvmCross.Binding.Interfaces;
namespace Cirrious.MvvmCross.Binding.Android.Target
{
public class MvxEditTextTextTargetBinding : MvxPropertyInfoTargetBinding<EditText>
{
public MvxEditTextTextTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
var editText = View;
if (editText == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error,"Error - EditText is null in MvxEditTextTextTargetBinding");
}
else
{
editText.AfterTextChanged += EditTextOnAfterTextChanged;
}
}
private void EditTextOnAfterTextChanged(object sender, AfterTextChangedEventArgs afterTextChangedEventArgs)
{
FireValueChanged(View.Text);
}
public override MvxBindingMode DefaultMode
{
get
{
return MvxBindingMode.TwoWay;
}
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var editText = View;
if (editText != null)
{
editText.AfterTextChanged -= EditTextOnAfterTextChanged;
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,54 @@
using System;
using Android.Graphics.Drawables;
using Android.Widget;
using Cirrious.MvvmCross.Binding.Interfaces;
namespace Cirrious.MvvmCross.Binding.Android.Target
{
public class MvxImageViewDrawableTargetBinding
: MvxBaseAndroidTargetBinding
{
private readonly ImageView _imageView;
public MvxImageViewDrawableTargetBinding(ImageView imageView)
{
_imageView = imageView;
}
public override void SetValue(object value)
{
if (value == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning, "Null value passed to ImageView binding");
return;
}
var stringValue = value as string;
if (string.IsNullOrWhiteSpace(stringValue))
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning, "Empty value passed to ImageView binding");
return;
}
var drawableResourceName = GetImageAssetName(stringValue);
var assetStream = AndroidGlobals.ApplicationContext.Assets.Open(drawableResourceName);
Drawable drawable = Drawable.CreateFromStream(assetStream, null);
_imageView.SetImageDrawable(drawable);
}
private static string GetImageAssetName(string rawImage)
{
return rawImage.TrimStart('/');
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
public override Type TargetType
{
get { return typeof(string); }
}
}
}

Просмотреть файл

@ -0,0 +1,8 @@
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public interface IMvxBindableListItemView
{
int TemplateId { get; }
void BindTo(object source);
}
}

Просмотреть файл

@ -0,0 +1,52 @@
using System;
using System.Collections;
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 sealed class MvxBindableLinearLayout
: LinearLayout
{
public MvxBindableListAdapterWithChangedEvent Adapter { get; set; }
public MvxBindableLinearLayout(Context context, IAttributeSet attrs)
: base(context, attrs)
{
var itemTemplateId = MvxBindableListViewHelpers.ReadTemplatePath(context, attrs);
Adapter = new MvxBindableListAdapterWithChangedEvent(context, itemTemplateId);
Adapter.DataSetChanged += AdapterOnDataSetChanged;
}
private void AdapterOnDataSetChanged(object sender, EventArgs eventArgs)
{
this.Refill(Adapter);
}
public IList ItemsSource
{
get { return Adapter.ItemsSource; }
set { Adapter.ItemsSource = value; }
}
public int ItemTemplateId
{
get { return Adapter.ItemTemplateId; }
set { Adapter.ItemTemplateId = value; }
}
}
}

Просмотреть файл

@ -0,0 +1,191 @@
using System.Collections;
using System.Collections.Specialized;
using Android;
using Android.Content;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Views;
using Cirrious.MvvmCross.Exceptions;
using Object = Java.Lang.Object;
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public class MvxBindableListAdapter
: BaseAdapter
{
private readonly Context _context;
private readonly IMvxBindingActivity _bindingActivity;
protected Context Context { get { return _context; } }
protected IMvxBindingActivity BindingActivity { get { return _bindingActivity; } }
public MvxBindableListAdapter(Context context, int itemTemplateId)
{
_itemTemplateId = itemTemplateId;
_context = context;
_bindingActivity = context as IMvxBindingActivity;
if (_bindingActivity == null)
throw new MvxException("MvxBindableListView can only be used within a Context which supports IMvxBindingActivity");
}
private IList _itemsSource;
public IList ItemsSource
{
get { return _itemsSource; }
set {
SetItemsSource(value);
}
}
private 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();
}
private int _itemTemplateId;
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 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(MvxBindingTraceLevel.Error, "GetView called when ItemsSource is null");
return null;
}
if (position < 0 || position >= _itemsSource.Count)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error, "GetView called with invalid Position - zero indexed {0} out of {1}", position, _itemsSource.Count);
return null;
}
var source = _itemsSource[position];
if (ItemTemplateId == 0)
{
// no template seen - so use a standard string view from Android and use ToString()
return GetSimpleView(convertView, source);
}
else
{
// we have a template so lets use bind and inflate on it :)
return GetBindableView(convertView, source);
}
}
public override int Count
{
get
{
if (_itemsSource == null)
return 0;
return _itemsSource.Count;
}
}
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)
{
var viewToUse = convertView as IMvxBindableListItemView;
if (viewToUse != null)
{
if (viewToUse.TemplateId != ItemTemplateId)
{
viewToUse = null;
}
}
if (viewToUse == null)
{
viewToUse = CreateBindableView(source);
}
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)
{
return new MvxBindableListItemView(_context, _bindingActivity, ItemTemplateId, source);
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
using System;
using Android.Content;
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public class MvxBindableListAdapterWithChangedEvent
: MvxBindableListAdapter
{
public MvxBindableListAdapterWithChangedEvent(Context context, int itemTemplateId)
: base(context, itemTemplateId)
{
}
public event EventHandler DataSetChanged;
public override void NotifyDataSetChanged()
{
base.NotifyDataSetChanged();
var handler = DataSetChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
}
}

Просмотреть файл

@ -0,0 +1,53 @@
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 MvxBindableListItemView
: FrameLayout
, IMvxBindableListItemView
{
private readonly View _content;
protected View Content { get { return _content; } }
private readonly int _templateId;
public int TemplateId
{
get { return _templateId; }
}
public MvxBindableListItemView(Context context, IMvxBindingActivity bindingActivity, int templateId, object source)
: base(context)
{
_templateId = templateId;
_content = bindingActivity.BindingInflate(source, templateId, this);
}
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;
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,57 @@
using System.Collections;
using Android.Content;
using Android.Runtime;
using Android.Util;
using Android.Widget;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Views;
using Cirrious.MvvmCross.Interfaces.Commands;
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public sealed class MvxBindableListView
: ListView
{
public new MvxBindableListAdapter Adapter
{
get { return base.Adapter as MvxBindableListAdapter; }
set { base.Adapter = value; }
}
public MvxBindableListView(Context context, IAttributeSet attrs)
: base(context, attrs)
{
var itemTemplateId = MvxBindableListViewHelpers.ReadTemplatePath(context, attrs);
Adapter = new MvxBindableListAdapter(context, itemTemplateId);
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);
};
}
public IList 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; }
}
}

Просмотреть файл

@ -0,0 +1,31 @@
using Android.Content;
using Android.Util;
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public static class MvxBindableListViewHelpers
{
public static int ReadTemplatePath(Context context, IAttributeSet attrs)
{
var typedArray = context.ObtainStyledAttributes(attrs, MvxAndroidBindingResource.Instance.BindableListViewStylableGroupId);
try
{
var numStyles = typedArray.IndexCount;
for (var i = 0; i < numStyles; ++i)
{
var attributeId = typedArray.GetIndex(i);
if (attributeId == MvxAndroidBindingResource.Instance.BindableListItemTemplateId)
{
return typedArray.GetResourceId(attributeId, 0);
}
}
return 0;
}
finally
{
typedArray.Recycle();
}
}
}
}

Просмотреть файл

@ -0,0 +1,65 @@
using System;
using System.Xml;
using Android.Views;
using Cirrious.MvvmCross.Android.Views;
using Cirrious.MvvmCross.Binding.Android.Binders;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Views;
using Cirrious.MvvmCross.Interfaces.ViewModels;
namespace Cirrious.MvvmCross.Binding.Android.Views
{
public abstract class MvxBindingActivityView<TViewModel>
: MvxActivityView<TViewModel>
, IMvxBindingActivity
where TViewModel : class, IMvxViewModel
{
public override global::Android.Views.LayoutInflater LayoutInflater
{
get
{
throw new InvalidOperationException("LayoutInflater must not be accessed directly in MvxBindingActivityView - use IMvxBindingActivity.BindingInflate or IMvxBindingActivity.NonBindingInflate instead");
}
}
public override void SetContentView(int layoutResId)
{
var view = BindingInflate(ViewModel, layoutResId, null);
SetContentView(view);
}
public View BindingInflate(object source, int resourceId, ViewGroup viewGroup)
{
return CommonInflate(
resourceId,
viewGroup,
(layoutInflator) => new MvxBindingLayoutInflatorFactory(source, layoutInflator));
}
public View NonBindingInflate(int resourceId, ViewGroup viewGroup)
{
return CommonInflate(
resourceId,
viewGroup,
(layoutInflator) => null);
}
private View CommonInflate(int resourceId, ViewGroup viewGroup, Func<LayoutInflater, MvxBindingLayoutInflatorFactory> factoryProvider)
{
var layoutInflator = base.LayoutInflater;
using (var clone = layoutInflator.CloneInContext(this))
{
using (var factory = factoryProvider(clone))
{
if (factory != null)
clone.Factory = factory;
var toReturn = clone.Inflate(resourceId, viewGroup);
if (factory != null)
{
factory.StoreBindings(toReturn);
}
return toReturn;
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
using Cirrious.MvvmCross.Binding.Interfaces;
namespace Cirrious.MvvmCross.Binding.Binders.Json
{
public class MvxJsonBindingDescription
{
#warning if monotouch then this might need a preserve!
public string Path { get; set; }
public string Converter { get; set; }
public string ConverterParameter { get; set; }
public string FallbackValue { get; set; }
public MvxBindingMode Mode { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,53 @@
using System.Collections.Generic;
using System.Linq;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Binders;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.Converters;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
namespace Cirrious.MvvmCross.Binding.Binders.Json
{
public class MvxJsonBindingDescriptionParser
: IMvxBindingDescriptionParser
, IMvxServiceConsumer<IMvxValueConverterProvider>
{
public IEnumerable<MvxBindingDescription> Parse(string text)
{
MvxJsonBindingSpecification specification;
var parser = new MvxJsonBindingParser();
if (!parser.TryParseBindingSpecification(text, out specification))
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error,
"Failed to parse binding specification starting with " +
(text.Length > 20 ? text.Substring(0,20) : text));
return null;
}
if (specification == null)
return null;
return from item in specification
let targetName = item.Key
let jsonDescription = item.Value
let converter = FindConverter(jsonDescription.Converter)
select new MvxBindingDescription()
{
TargetName = targetName,
SourcePropertyPath = jsonDescription.Path,
Converter = converter,
ConverterParameter = jsonDescription.ConverterParameter,
Mode = jsonDescription.Mode,
FallbackValue = jsonDescription.FallbackValue
};
}
private IMvxValueConverter FindConverter(string converterName)
{
if (string.IsNullOrWhiteSpace(converterName))
return null;
return this.GetService<IMvxValueConverterProvider>().Find(converterName);
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
using System;
using System.Threading;
using Cirrious.MvvmCross.ExtensionMethods;
namespace Cirrious.MvvmCross.Binding.Binders.Json
{
public class MvxJsonBindingParser
{
public bool TryParseBindingSpecification(string text, out MvxJsonBindingSpecification requestedBindings)
{
if (string.IsNullOrWhiteSpace(text))
{
requestedBindings = new MvxJsonBindingSpecification();
return false;
}
try
{
requestedBindings = Newtonsoft.Json.JsonConvert.DeserializeObject<MvxJsonBindingSpecification>(text);
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
requestedBindings = null;
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error,"Problem parsing Json tag for databinding " + exception.ToLongString());
return false;
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace Cirrious.MvvmCross.Binding.Binders.Json
{
public class MvxJsonBindingSpecification
: Dictionary<string, MvxJsonBindingDescription>
{
#warning if monotouch then this might need a preserve!
}
}

Просмотреть файл

@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Linq;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Binders;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
namespace Cirrious.MvvmCross.Binding.Binders
{
public class MvxFromTextBinder
: IMvxBinder
, IMvxServiceConsumer<IMvxBindingDescriptionParser>
{
public IEnumerable<IMvxUpdateableBinding> Bind(object source, object target, string bindingText)
{
var bindingDescriptions = this.GetService<IMvxBindingDescriptionParser>().Parse(bindingText);
if (bindingDescriptions == null)
return null;
return Bind(source, target, bindingDescriptions);
}
public IEnumerable<IMvxUpdateableBinding> Bind(object source, object target, IEnumerable<MvxBindingDescription> bindingDescriptions)
{
return bindingDescriptions.Select(description => Bind(new MvxBindingRequest(source, target, description)));
}
public IMvxUpdateableBinding Bind(MvxBindingRequest bindingRequest)
{
return new MvxFullBinding(bindingRequest);
}
}
}

Просмотреть файл

@ -0,0 +1,279 @@
using System;
using System.Globalization;
using System.Threading;
using Cirrious.MvvmCross.Binding.Bindings;
using Cirrious.MvvmCross.Binding.Bindings.Target;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source.Construction;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction;
using Cirrious.MvvmCross.Exceptions;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
namespace Cirrious.MvvmCross.Binding.Binders
{
public class MvxFullBinding
: MvxBaseBinding
, IMvxUpdateableBinding
, IMvxServiceConsumer<IMvxTargetBindingFactory>
, IMvxServiceConsumer<IMvxSourceBindingFactory>
{
private IMvxSourceBindingFactory SourceBindingFactory
{
get { return this.GetService<IMvxSourceBindingFactory>(); }
}
private IMvxTargetBindingFactory TargetBindingFactory
{
get { return this.GetService<IMvxTargetBindingFactory>(); }
}
private MvxBindingDescription _bindingDescription;
private IMvxSourceBinding _sourceBinding;
private IMvxTargetBinding _targetBinding;
private object _dataContext;
public object DataContext
{
get { return _dataContext; }
set
{
if (_dataContext == value)
return;
ClearSourceBinding();
CreateSourceBinding(value);
}
}
public MvxFullBinding(MvxBindingRequest bindingRequest)
{
_bindingDescription = bindingRequest.Description;
CreateTargetBinding(bindingRequest.Target);
CreateSourceBinding(bindingRequest.Source);
}
private void ClearSourceBinding()
{
if (_sourceBinding != null)
{
_sourceBinding.Dispose();
_sourceBinding = null;
}
}
private void CreateSourceBinding(object source)
{
_dataContext = source;
_sourceBinding = SourceBindingFactory.CreateBinding(source, _bindingDescription.SourcePropertyPath);
if (NeedToObserveSourceChanges)
_sourceBinding.Changed += (sender, args) => UpdateTargetFromSource(args.IsAvailable, args.Value);
if (NeedToUpdateTargetOnBind)
{
// note that we expect Bind to be called on the UI thread - so no need to use RunOnUIThread here
object currentValue;
bool currentIsAvailable = _sourceBinding.TryGetValue(out currentValue);
UpdateTargetFromSource(currentIsAvailable, currentValue);
}
}
private void CreateTargetBinding(object target)
{
_targetBinding = TargetBindingFactory.CreateBinding(target, _bindingDescription);
if (_targetBinding == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning,
"Failed to create target binding for {0}", _bindingDescription.ToString());
_targetBinding = new MvxNullTargetBinding();
}
if (NeedToObserveTargetChanges)
{
_targetBinding.ValueChanged += (sender, args) => UpdateSourceFromTarget(args.Value);
}
}
private void UpdateTargetFromSource(
bool isAvailable,
object value)
{
try
{
if (isAvailable)
{
if (_bindingDescription.Converter != null)
value =
_bindingDescription.Converter.Convert(value,
_targetBinding.TargetType,
_bindingDescription.ConverterParameter,
CultureInfo.CurrentUICulture);
}
else
{
value = _bindingDescription.FallbackValue;
}
_targetBinding.SetValue(value);
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
MvxBindingTrace.Trace(
MvxBindingTraceLevel.Error,
"Problem seen during binding execution for {0} - problem {1}",
_bindingDescription.ToString(),
exception.ToLongString());
}
}
private void UpdateSourceFromTarget(
object value)
{
try
{
if (_bindingDescription.Converter != null)
value =
_bindingDescription.Converter.ConvertBack(value,
_sourceBinding.SourceType,
_bindingDescription.ConverterParameter,
CultureInfo.CurrentUICulture);
_sourceBinding.SetValue(value);
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
MvxBindingTrace.Trace(
MvxBindingTraceLevel.Error,
"Problem seen during binding execution for {0} - problem {1}",
_bindingDescription.ToString(),
exception.ToLongString());
}
}
private static void UpdateSourceFromTarget(MvxBindingRequest bindingRequest, IMvxSourceBinding sourceBinding, object value)
{
try
{
if (bindingRequest.Description.Converter != null)
value =
bindingRequest.Description.Converter.ConvertBack(value,
sourceBinding.SourceType,
bindingRequest.Description.ConverterParameter,
CultureInfo.CurrentUICulture);
sourceBinding.SetValue(value);
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
MvxBindingTrace.Trace(
MvxBindingTraceLevel.Error,
"Problem seen during binding execution for {0} - problem {1}",
bindingRequest.ToString(),
exception.ToLongString());
}
}
protected bool NeedToObserveSourceChanges
{
get
{
switch (ActualBindingMode)
{
case MvxBindingMode.Default:
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning, "Mode of default seen for binding - assuming OneWay");
return true;
case MvxBindingMode.OneWay:
case MvxBindingMode.TwoWay:
return true;
case MvxBindingMode.OneTime:
case MvxBindingMode.OneWayToSource:
return false;
default:
throw new MvxException("Unexpected ActualBindingMode");
}
}
}
protected bool NeedToObserveTargetChanges
{
get
{
switch (ActualBindingMode)
{
case MvxBindingMode.Default:
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning, "Mode of default seen for binding - assuming OneWay");
return true;
case MvxBindingMode.OneWay:
case MvxBindingMode.OneTime:
return false;
case MvxBindingMode.TwoWay:
case MvxBindingMode.OneWayToSource:
return true;
default:
throw new MvxException("Unexpected ActualBindingMode");
}
}
}
protected bool NeedToUpdateTargetOnBind
{
get
{
switch (ActualBindingMode)
{
case MvxBindingMode.Default:
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning, "Mode of default seen for binding - assuming OneWay");
return true;
case MvxBindingMode.OneWay:
case MvxBindingMode.OneTime:
case MvxBindingMode.TwoWay:
return true;
case MvxBindingMode.OneWayToSource:
return true;
default:
throw new MvxException("Unexpected ActualBindingMode");
}
}
}
private MvxBindingMode ActualBindingMode
{
get
{
var mode = _bindingDescription.Mode;
if (mode == MvxBindingMode.Default)
mode = _targetBinding.DefaultMode;
return mode;
}
}
#warning Go through all libraries and just do Dispose properly! Add GC.SuppressFinalize(this)
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
if (_targetBinding != null)
_targetBinding.Dispose();
if (_sourceBinding != null)
_sourceBinding.Dispose();
}
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
using System;
using System.Linq;
using Cirrious.MvvmCross.Binding.Interfaces.Binders;
using Cirrious.MvvmCross.Interfaces.Converters;
namespace Cirrious.MvvmCross.Binding.Binders
{
public class MvxStaticBasedValueConverterRegistryFiller
{
private readonly IMvxValueConverterRegistry _registry;
public MvxStaticBasedValueConverterRegistryFiller(IMvxValueConverterRegistry registry)
{
_registry = registry;
}
public void AddStaticFieldConverters(Type type)
{
var pairs = from field in type.GetFields()
where field.IsStatic
where field.IsPublic
where typeof (IMvxValueConverter).IsAssignableFrom(field.FieldType)
let converter = field.GetValue(null) as IMvxValueConverter
where converter != null
select new {
Name = field.Name,
Converter = converter
};
foreach (var pair in pairs)
{
_registry.AddOrOverwrite(pair.Name, pair.Converter);
}
}
}
}

Просмотреть файл

@ -0,0 +1,28 @@
using System.Collections.Generic;
using Cirrious.MvvmCross.Binding.Interfaces.Binders;
using Cirrious.MvvmCross.Interfaces.Converters;
namespace Cirrious.MvvmCross.Binding.Binders
{
public class MvxValueConverterRegistry
: IMvxValueConverterProvider
, IMvxValueConverterRegistry
{
private readonly Dictionary<string, IMvxValueConverter> _converters = new Dictionary<string, IMvxValueConverter>();
public IMvxValueConverter Find(string converterName)
{
IMvxValueConverter toReturn;
if (!_converters.TryGetValue(converterName, out toReturn))
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning,"Could not find named converter " + converterName);
}
return toReturn;
}
public void AddOrOverwrite(string name, IMvxValueConverter converter)
{
_converters[name] = converter;
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
using Cirrious.MvvmCross.Binding.Interfaces;
namespace Cirrious.MvvmCross.Binding.Bindings
{
public abstract class MvxBaseBinding : IMvxBinding
{
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool isDisposing)
{
// nothing to do in this base class
}
}
}

Просмотреть файл

@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Linq;
using Cirrious.MvvmCross.Binding.Interfaces;
namespace Cirrious.MvvmCross.Binding.Bindings
{
public class MvxCompositeBinding : MvxBaseBinding
{
private readonly List<IMvxBinding> _bindings;
public MvxCompositeBinding(params IMvxBinding[] args)
{
_bindings = args.ToList();
}
public void Add(params IMvxBinding[] args)
{
_bindings.AddRange(args);
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
_bindings.ForEach(x => x.Dispose());
_bindings.Clear();
}
base.Dispose(isDisposing);
}
}
}

Просмотреть файл

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source.Construction;
namespace Cirrious.MvvmCross.Binding.Bindings.Source.Construction
{
public class MvxSourceBindingFactory : IMvxSourceBindingFactory
{
private static readonly char[] FieldSeparator = new [] { '.' };
public IMvxSourceBinding CreateBinding(object source, string combinedPropertyName)
{
if (combinedPropertyName == null)
combinedPropertyName = "";
return CreateBinding(source, combinedPropertyName.Split(FieldSeparator , StringSplitOptions.RemoveEmptyEntries));
}
public IMvxSourceBinding CreateBinding(object source, IEnumerable<string> childPropertyNames)
{
var childPropertyNameList = childPropertyNames.ToList();
switch (childPropertyNameList.Count)
{
case 0:
return new MvxDirectToSourceBinding(source);
case 1:
return new MvxPropertyInfoSourceBinding(source, childPropertyNameList.DefaultIfEmpty(string.Empty).FirstOrDefault());
default:
return new MvxChainedSourceBinding(source, childPropertyNameList.First(), childPropertyNameList.Skip(1));
}
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
using System;
using System.ComponentModel;
using System.Reflection;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source;
namespace Cirrious.MvvmCross.Binding.Bindings.Source
{
public abstract class MvxBasePropertyInfoSourceBinding : MvxBaseSourceBinding
{
private readonly string _propertyName;
private readonly PropertyInfo _propertyInfo;
protected string PropertyName { get { return _propertyName; } }
protected PropertyInfo PropertyInfo { get { return _propertyInfo; } }
protected MvxBasePropertyInfoSourceBinding(object source, string propertyName)
: base(source)
{
_propertyName = propertyName;
if (Source == null)
{
MvxBindingTrace.Trace(
MvxBindingTraceLevel.Warning,
"Unable to bind to source is null"
, propertyName);
return;
}
_propertyInfo = source.GetType().GetProperty(propertyName);
if (_propertyInfo == null)
{
MvxBindingTrace.Trace(
MvxBindingTraceLevel.Warning,
"Unable to bind: source property source not found {0} on {1}"
, propertyName,
source.GetType().Name);
}
var sourceNotify = Source as INotifyPropertyChanged;
if (sourceNotify != null)
sourceNotify.PropertyChanged += new PropertyChangedEventHandler(SourcePropertyChanged);
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
var sourceNotify = Source as INotifyPropertyChanged;
if (sourceNotify != null)
sourceNotify.PropertyChanged -= SourcePropertyChanged;
}
}
private void SourcePropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == PropertyName)
OnBoundPropertyChanged();
}
protected abstract void OnBoundPropertyChanged();
}
}

Просмотреть файл

@ -0,0 +1,32 @@
using System;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source;
namespace Cirrious.MvvmCross.Binding.Bindings.Source
{
public abstract class MvxBaseSourceBinding
: MvxBaseBinding
, IMvxSourceBinding
{
private readonly object _source;
protected object Source { get { return _source; } }
protected MvxBaseSourceBinding(object source)
{
_source = source;
}
public event EventHandler<MvxSourcePropertyBindingEventArgs> Changed;
protected void FireChanged(MvxSourcePropertyBindingEventArgs args)
{
var handler = Changed;
if (handler != null)
handler(this, args);
}
public abstract void SetValue(object value);
public abstract Type SourceType { get; }
public abstract bool TryGetValue(out object value);
}
}

Просмотреть файл

@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source.Construction;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
namespace Cirrious.MvvmCross.Binding.Bindings.Source
{
public class MvxChainedSourceBinding
: MvxBasePropertyInfoSourceBinding
, IMvxServiceConsumer<IMvxSourceBindingFactory>
{
private IMvxSourceBindingFactory SourceBindingFactory
{
get { return this.GetService<IMvxSourceBindingFactory>(); }
}
private readonly List<string> _childPropertyNames;
private IMvxSourceBinding _currentChildBinding;
public MvxChainedSourceBinding(
object source,
string propertyName,
IEnumerable<string> childPropertyNames)
: base(source, propertyName)
{
_childPropertyNames = childPropertyNames.ToList();
UpdateChildBinding();
}
private void UpdateChildBinding()
{
if (_currentChildBinding != null)
{
_currentChildBinding.Changed -= ChildSourceBindingChanged;
_currentChildBinding = null;
}
if (PropertyInfo == null)
{
return;
}
var currentValue = PropertyInfo.GetValue(Source, null);
if (currentValue == null)
{
// value will be missing... so end consumer will need to use fallback values
return;
}
else
{
_currentChildBinding = SourceBindingFactory.CreateBinding(currentValue, _childPropertyNames);
_currentChildBinding.Changed += ChildSourceBindingChanged;
}
}
void ChildSourceBindingChanged(object sender, MvxSourcePropertyBindingEventArgs e)
{
FireChanged(e);
}
protected override void OnBoundPropertyChanged()
{
UpdateChildBinding();
FireChanged(new MvxSourcePropertyBindingEventArgs(this));
}
public override bool TryGetValue(out object value)
{
if (_currentChildBinding == null)
{
value = null;
return false;
}
return _currentChildBinding.TryGetValue(out value);
}
public override void SetValue(object value)
{
if (_currentChildBinding == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning, "SetValue ignored in binding - target property path missing");
return;
}
_currentChildBinding.SetValue(value);
}
public override Type SourceType
{
get { throw new NotImplementedException(); }
}
}
}

Просмотреть файл

@ -0,0 +1,32 @@
using System;
namespace Cirrious.MvvmCross.Binding.Bindings.Source
{
public class MvxDirectToSourceBinding : MvxBaseSourceBinding
{
public MvxDirectToSourceBinding(object source)
: base(source)
{
}
public override void SetValue(object value)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning,
"ToSource binding is not available for direct pathed source bindings");
}
public override Type SourceType
{
get
{
return Source == null ? typeof (object) : Source.GetType(); }
}
public override bool TryGetValue(out object value)
{
value = Source;
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,72 @@
using System;
using System.Threading;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source;
using Cirrious.MvvmCross.ExtensionMethods;
namespace Cirrious.MvvmCross.Binding.Bindings.Source
{
public class MvxPropertyInfoSourceBinding : MvxBasePropertyInfoSourceBinding
{
public MvxPropertyInfoSourceBinding(object source, string propertyName)
: base(source, propertyName)
{
}
protected override void OnBoundPropertyChanged()
{
FireChanged(new MvxSourcePropertyBindingEventArgs(this));
}
public override bool TryGetValue(out object value)
{
if (PropertyInfo == null)
{
value = null;
return false;
}
if (!PropertyInfo.CanRead)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error,"SetValue ignored in binding - target property is writeonly");
value = null;
return false;
}
value = PropertyInfo.GetValue(Source, null);
return true;
}
public override void SetValue(object value)
{
if (PropertyInfo == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning,"SetValue ignored in binding - target property missing");
return;
}
if (!PropertyInfo.CanWrite)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Warning, "SetValue ignored in binding - target property is readonly");
return;
}
try
{
PropertyInfo.SetValue(Source, value, null);
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error, "SetValue failed with exception - " + exception.ToLongString());
}
}
public override Type SourceType
{
get { return (PropertyInfo == null) ? null : PropertyInfo.PropertyType; }
}
}
}

Просмотреть файл

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction;
namespace Cirrious.MvvmCross.Binding.Bindings.Target.Construction
{
public class MvxCustomBindingFactory<TTarget>
: IMvxPluginTargetBindingFactory
where TTarget : class
{
private readonly string _targetFakePropertyName;
private readonly Func<TTarget, IMvxTargetBinding> _targetBindingCreator;
public MvxCustomBindingFactory(string targetFakePropertyName, Func<TTarget, IMvxTargetBinding> targetBindingCreator)
{
_targetFakePropertyName = targetFakePropertyName;
_targetBindingCreator = targetBindingCreator;
}
public IEnumerable<MvxTypeAndNamePair> SupportedTypes
{
get { return new[] { new MvxTypeAndNamePair(typeof(TTarget), _targetFakePropertyName) }; }
}
public IMvxTargetBinding CreateBinding(object target, MvxBindingDescription description)
{
var castTarget = target as TTarget;
if (castTarget == null)
{
MvxBindingTrace.Trace(MvxBindingTraceLevel.Error, "Passed an invalid target for MvxCustomBindingFactory");
return null;
}
return _targetBindingCreator(castTarget);
}
}
}

Просмотреть файл

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction;
namespace Cirrious.MvvmCross.Binding.Bindings.Target.Construction
{
public class MvxPropertyInfoTargetBindingFactory
: IMvxPluginTargetBindingFactory
{
private readonly Type _targetType;
private readonly string _targetName;
private readonly Func<object, PropertyInfo, IMvxTargetBinding> _bindingCreator;
protected Type TargetType { get { return _targetType; } }
public MvxPropertyInfoTargetBindingFactory(Type targetType, string targetName, Func<object, PropertyInfo, IMvxTargetBinding> bindingCreator)
{
_targetType = targetType;
_targetName = targetName;
_bindingCreator = bindingCreator;
}
public IEnumerable<MvxTypeAndNamePair> SupportedTypes
{
get { return new[] {new MvxTypeAndNamePair() {Name = _targetName, Type = _targetType}}; }
}
public IMvxTargetBinding CreateBinding(object target, MvxBindingDescription description)
{
var targetPropertyInfo = target.GetType().GetProperty(description.TargetName);
if (targetPropertyInfo != null)
{
try
{
return _bindingCreator(target, targetPropertyInfo);
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
MvxBindingTrace.Trace(
MvxBindingTraceLevel.Error,
"Problem creating target binding for {0} - exception {1}", _targetType.Name, exception.ToString());
}
}
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction;
namespace Cirrious.MvvmCross.Binding.Bindings.Target.Construction
{
public class MvxSimplePropertyInfoTargetBindingFactory
: IMvxPluginTargetBindingFactory
{
private readonly MvxPropertyInfoTargetBindingFactory _innerFactory;
private readonly Type _bindingType;
public MvxSimplePropertyInfoTargetBindingFactory(Type bindingType, Type targetType, string targetName)
{
_bindingType = bindingType;
_innerFactory = new MvxPropertyInfoTargetBindingFactory(targetType, targetName, CreateTargetBinding);
}
private IMvxTargetBinding CreateTargetBinding(object target, PropertyInfo targetPropertyInfo)
{
var targetBindingCandidate = Activator.CreateInstance(_bindingType, new object[] {target, targetPropertyInfo });
var targetBinding = targetBindingCandidate as IMvxTargetBinding;
if (targetBinding == null)
{
var disposable = targetBindingCandidate as IDisposable;
if (disposable != null)
disposable.Dispose();
}
return targetBinding;
}
public IEnumerable<MvxTypeAndNamePair> SupportedTypes
{
get { return _innerFactory.SupportedTypes; }
}
public IMvxTargetBinding CreateBinding(object target, MvxBindingDescription description)
{
return _innerFactory.CreateBinding(target, description);
}
}
}

Просмотреть файл

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction;
namespace Cirrious.MvvmCross.Binding.Bindings.Target.Construction
{
public class MvxTargetBindingFactoryRegistry : IMvxTargetBindingFactoryRegistry
{
private string GenerateKey(Type type, string name)
{
return string.Format("{0}:{1}", type.FullName, name);
}
private readonly Dictionary<string, IMvxPluginTargetBindingFactory> _lookups =
new Dictionary<string, IMvxPluginTargetBindingFactory>();
private IMvxPluginTargetBindingFactory FindSpecificFactory(Type type, string name)
{
IMvxPluginTargetBindingFactory factory;
var key = GenerateKey(type, name);
if (_lookups.TryGetValue(key, out factory))
{
return factory;
}
var baseType = type.BaseType;
if (baseType != null)
return FindSpecificFactory(baseType, name);
return null;
}
public IMvxTargetBinding CreateBinding(object target, MvxBindingDescription description)
{
var factory = FindSpecificFactory(target.GetType(), description.TargetName);
if (factory != null)
return factory.CreateBinding(target, description);
var targetPropertyInfo = target.GetType().GetProperty(description.TargetName);
if (targetPropertyInfo != null)
{
return new MvxPropertyInfoTargetBinding(target, targetPropertyInfo);
}
var targetEventInfo = target.GetType().GetEvent(description.TargetName);
if (targetEventInfo != null)
{
#warning Handle other event types here - possibly another lookup table so people can register their own?
if (targetEventInfo.EventHandlerType == typeof(EventHandler))
return new MvxEventHandlerEventInfoTargetBinding(target, targetEventInfo);
}
return null;
}
public void RegisterFactory(IMvxPluginTargetBindingFactory factory)
{
foreach (var supported in factory.SupportedTypes)
{
var key = GenerateKey(supported.Type, supported.Name);
_lookups[key] = factory;
}
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using System;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target;
namespace Cirrious.MvvmCross.Binding.Bindings.Target
{
public abstract class MvxBaseTargetBinding : MvxBaseBinding, IMvxTargetBinding
{
public abstract Type TargetType { get; }
public abstract void SetValue(object value);
public event EventHandler<MvxTargetChangedEventArgs> ValueChanged;
public abstract MvxBindingMode DefaultMode { get; }
protected virtual void FireValueChanged(object newValue)
{
var handler = ValueChanged;
if (handler != null)
handler(this, new MvxTargetChangedEventArgs(newValue));
}
}
}

Просмотреть файл

@ -0,0 +1,51 @@
using System;
using System.Reflection;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Interfaces.Commands;
namespace Cirrious.MvvmCross.Binding.Bindings.Target
{
public class MvxEventHandlerEventInfoTargetBinding : MvxBaseTargetBinding
{
private readonly object _target;
private readonly EventInfo _targetEventInfo;
private IMvxCommand _currentCommand;
public MvxEventHandlerEventInfoTargetBinding(object target, EventInfo targetEventInfo)
{
_target = target;
_targetEventInfo = targetEventInfo;
_targetEventInfo.AddEventHandler(_target, new EventHandler(HandleEvent));
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
_targetEventInfo.RemoveEventHandler(_target, new EventHandler(HandleEvent));
}
private void HandleEvent(object sender, EventArgs args)
{
if (_currentCommand != null)
_currentCommand.Execute();
}
public override Type TargetType
{
get { return typeof (IMvxCommand); }
}
public override void SetValue(object value)
{
var command = value as IMvxCommand;
_currentCommand = command;
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
}
}

Просмотреть файл

@ -0,0 +1,52 @@
using System;
using System.Reflection;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Interfaces.Commands;
namespace Cirrious.MvvmCross.Binding.Bindings.Target
{
public class MvxEventInfoTargetBinding<T> : MvxBaseTargetBinding
where T : EventArgs
{
private readonly object _target;
private readonly EventInfo _targetEventInfo;
private IMvxCommand _currentCommand;
public MvxEventInfoTargetBinding(object target, EventInfo targetEventInfo)
{
_target = target;
_targetEventInfo = targetEventInfo;
_targetEventInfo.AddEventHandler(_target, new EventHandler<T>(HandleEvent));
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
_targetEventInfo.RemoveEventHandler(_target, new EventHandler<T>(HandleEvent));
}
private void HandleEvent(object sender, T args)
{
if (_currentCommand != null)
_currentCommand.Execute();
}
public override Type TargetType
{
get { return typeof (IMvxCommand); }
}
public override void SetValue(object value)
{
var command = value as IMvxCommand;
_currentCommand = command;
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using System;
using Cirrious.MvvmCross.Binding.Interfaces;
namespace Cirrious.MvvmCross.Binding.Bindings.Target
{
public class MvxNullTargetBinding : MvxBaseTargetBinding
{
public override void SetValue(object value)
{
// ignored
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneTime; }
}
public override Type TargetType
{
get { return typeof(Object); }
}
}
}

Просмотреть файл

@ -0,0 +1,121 @@
using System;
using System.Reflection;
using Cirrious.MvvmCross.Binding.Interfaces;
namespace Cirrious.MvvmCross.Binding.Bindings.Target
{
public class MvxPropertyInfoTargetBinding : MvxBaseTargetBinding
{
private readonly object _target;
private readonly PropertyInfo _targetPropertyInfo;
private enum UpdatingState
{
None,
UpdatingSource,
UpdatingTarget
}
private UpdatingState _updatingState = UpdatingState.None;
protected object Target { get { return _target; } }
public MvxPropertyInfoTargetBinding(object target, PropertyInfo targetPropertyInfo)
{
_target = target;
_targetPropertyInfo = targetPropertyInfo;
}
public override Type TargetType
{
get { return _targetPropertyInfo.PropertyType; }
}
sealed public override void SetValue(object value)
{
if (_updatingState != UpdatingState.None)
return;
MvxBindingTrace.Trace(MvxBindingTraceLevel.Diagnostic,"Receiving setValue to " + (value ?? "").ToString());
try
{
_updatingState = UpdatingState.UpdatingTarget;
var safeValue = MakeValueSafeForTarget(value);
_targetPropertyInfo.SetValue(_target, safeValue, null);
}
finally
{
_updatingState = UpdatingState.None;
}
}
private object MakeValueSafeForTarget(object value)
{
object toReturn = value;
#warning not sure about value type hack here + could also add enum checking/parsing (Enum.ToObject())?
if (_targetPropertyInfo.PropertyType.IsValueType)
{
if (toReturn == null)
{
toReturn = Activator.CreateInstance(_targetPropertyInfo.PropertyType);
return toReturn;
}
}
if (_targetPropertyInfo.PropertyType == typeof (string))
{
if (!(toReturn is string))
{
if (toReturn != null)
{
toReturn = toReturn.ToString();
}
else
{
#warning not sure about string.empty here
toReturn = string.Empty;
}
}
}
return toReturn;
}
sealed protected override void FireValueChanged(object newValue)
{
if (_updatingState != UpdatingState.None)
return;
MvxBindingTrace.Trace(MvxBindingTraceLevel.Diagnostic, "Firing changed to " + (newValue ?? "").ToString());
try
{
_updatingState = UpdatingState.UpdatingSource;
base.FireValueChanged(newValue);
}
finally
{
_updatingState = UpdatingState.None;
}
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
}
public class MvxPropertyInfoTargetBinding<T> : MvxPropertyInfoTargetBinding
where T : class
{
public MvxPropertyInfoTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
}
protected T View
{
get { return base.Target as T; }
}
}
}

Просмотреть файл

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{47FD89C3-19DC-4BD2-9B6D-FB8363BE7EB9}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Cirrious.MvvmCross.Binding</RootNamespace>
<AssemblyName>Cirrious.MvvmCross.Binding.Android</AssemblyName>
<FileAlignment>512</FileAlignment>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidSupportedAbis>armeabi</AndroidSupportedAbis>
<AndroidStoreUncompressedFileExtensions />
<MandroidI18n />
<TargetFrameworkVersion>v1.6</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Android\Interfaces\Binders\IMvxViewTypeResolver.cs" />
<Compile Include="Android\Binders\MvxJavaBindingWrapper.cs" />
<Compile Include="Android\MvxJavaContainer.cs" />
<Compile Include="Android\Binders\MvxStackingLayoutInflatorFactory.cs" />
<Compile Include="Android\Binders\MvxViewTypeResolver.cs" />
<Compile Include="Android\Interfaces\Views\IMvxBindingActivity.cs" />
<Compile Include="Android\Interfaces\Binders\IMvxBindingLayoutInflator.cs" />
<Compile Include="Android\Interfaces\Binders\IMvxViewClassNameResolver.cs" />
<Compile Include="Android\Binders\MvxViewClassNameResolver.cs" />
<Compile Include="Android\MvxAndroidBindingResource.cs" />
<Compile Include="Android\Views\IMvxBindableListItemView.cs" />
<Compile Include="Android\Views\MvxBindableLinearLayout.cs" />
<Compile Include="Android\Views\MvxBindableListItemView.cs" />
<Compile Include="Android\Views\MvxBindableListView.cs" />
<Compile Include="Android\Views\MvxBindableListAdapter.cs" />
<Compile Include="Android\Views\MvxBindableListAdapterWithChangedEvent.cs" />
<Compile Include="Android\Views\MvxBindableListViewHelpers.cs" />
<Compile Include="Android\Views\MvxBindingActivityView.cs" />
<Compile Include="Android\Target\MvxBaseAndroidTargetBinding.cs" />
<Compile Include="Android\Target\MvxCompoundButtonCheckedTargetBinding.cs" />
<Compile Include="Android\Target\MvxImageViewDrawableTargetBinding.cs" />
<Compile Include="Bindings\Source\MvxBaseSourceBinding.cs" />
<Compile Include="Bindings\Source\MvxDirectToSourceBinding.cs" />
<Compile Include="Bindings\Target\Construction\MvxCustomBindingFactory.cs" />
<Compile Include="Bindings\Target\MvxNullTargetBinding.cs" />
<Compile Include="Interfaces\Binders\IMvxBindingDescriptionParser.cs" />
<Compile Include="Interfaces\Binders\IMvxValueConverterProvider.cs" />
<Compile Include="Binders\MvxValueConverterRegistry.cs" />
<Compile Include="Binders\MvxFromTextBinder.cs" />
<Compile Include="Binders\Json\MvxJsonBindingDescriptionParser.cs" />
<Compile Include="Binders\MvxStaticBasedValueConverterRegistryFiller.cs" />
<Compile Include="Android\Binders\MvxBindingLayoutInflatorFactory.cs" />
<Compile Include="Android\MvxAndroidBindingSetup.cs" />
<Compile Include="Android\Target\MvxEditTextTextTargetBinding.cs" />
<Compile Include="Android\ExtensionMethods\MvxTextSettingExtensions.cs" />
<Compile Include="Android\ExtensionMethods\MvxViewBindingExtensions.cs" />
<Compile Include="Interfaces\Binders\IMvxValueConverterRegistry.cs" />
<Compile Include="Interfaces\IMvxBinder.cs" />
<Compile Include="Interfaces\Bindings\Source\Construction\IMvxSourceBindingFactory.cs" />
<Compile Include="Interfaces\IMvxBinding.cs" />
<Compile Include="Bindings\MvxBaseBinding.cs" />
<Compile Include="Bindings\MvxCompositeBinding.cs" />
<Compile Include="Interfaces\Bindings\Source\IMvxSourceBinding.cs" />
<Compile Include="Bindings\Source\MvxBasePropertyInfoSourceBinding.cs" />
<Compile Include="Bindings\Source\MvxChainedSourceBinding.cs" />
<Compile Include="Bindings\Source\MvxPropertyInfoSourceBinding.cs" />
<Compile Include="Interfaces\Bindings\Source\MvxSourcePropertyBindingEventArgs.cs" />
<Compile Include="Interfaces\Bindings\Target\Construction\IMvxPluginTargetBindingFactory.cs" />
<Compile Include="Interfaces\Bindings\Target\Construction\IMvxTargetBindingFactory.cs" />
<Compile Include="Interfaces\Bindings\Target\Construction\IMvxTargetBindingFactoryRegistry.cs" />
<Compile Include="Bindings\Target\Construction\MvxPropertyInfoTargetBindingFactory.cs" />
<Compile Include="Bindings\Target\Construction\MvxSimplePropertyInfoTargetBindingFactory.cs" />
<Compile Include="Bindings\Target\Construction\MvxTargetBindingFactoryRegistry.cs" />
<Compile Include="Interfaces\Bindings\Target\Construction\MvxTypeAndNamePair.cs" />
<Compile Include="Interfaces\Bindings\Target\IMvxTargetBinding.cs" />
<Compile Include="Bindings\Target\MvxBaseTargetBinding.cs" />
<Compile Include="Bindings\Target\MvxEventHandlerEventInfoTargetBinding.cs" />
<Compile Include="Bindings\Target\MvxEventInfoTargetBinding.cs" />
<Compile Include="Interfaces\Bindings\Target\MvxTargetChangedEventArgs.cs" />
<Compile Include="Bindings\Target\MvxPropertyInfoTargetBinding.cs" />
<Compile Include="Binders\Json\MvxJsonBindingParser.cs" />
<Compile Include="Binders\Json\MvxJsonBindingDescription.cs" />
<Compile Include="Binders\Json\MvxJsonBindingSpecification.cs" />
<Compile Include="Binders\MvxFullBinding.cs" />
<Compile Include="Bindings\Source\Construction\MvxSourceBindingFactory.cs" />
<Compile Include="Interfaces\IMvxUpdateableBinding.cs" />
<Compile Include="Interfaces\MvxBindingDescription.cs" />
<Compile Include="Interfaces\MvxBindingMode.cs" />
<Compile Include="Interfaces\MvxBindingRequest.cs" />
<Compile Include="MvxBindingSetup.cs" />
<Compile Include="MvxBindingTraceLevel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MvxBindingTrace.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Library\Newtonsoft.Json\Newtonsoft.Json\Newtonsoft.Json.MonoDroid.csproj">
<Project>{E6C3413C-919B-486D-8B6C-225CBD921B98}</Project>
<Name>Newtonsoft.Json.MonoDroid</Name>
</ProjectReference>
<ProjectReference Include="..\Cirrious.MvvmCross\Cirrious.MvvmCross.Android.csproj">
<Project>{7A6BE137-D0F1-46A1-AE5C-81FAEEDDDF02}</Project>
<Name>Cirrious.MvvmCross.Android</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<AndroidAsset Include="ResourcesToCopy\MvxBindingAttributes.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{062250C5-A896-4FCF-AA34-7F2C370E682B}</ProjectGuid>
<ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<RootNamespace>Cirrious.MvvmCross.Binding</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<AssemblyName>Cirrious.MvvmCross.Binding.Touch</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<AssemblyName>Cirrious.MvvmCross.Binding.Touch</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AdHoc|iPhone' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\iPhone\AdHoc</OutputPath>
<WarningLevel>4</WarningLevel>
<AssemblyName>Cirrious.MvvmCross.Binding.Touch</AssemblyName>
<CodesignKey>iPhone Developer</CodesignKey>
<DefineConstants>MONOTOUCH</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|iPhone'">
<OutputPath>bin\iPhone\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|iPhone'">
<OutputPath>bin\iPhone\Release\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="monotouch">
<HintPath>..\..\Library\Hacked\monotouch.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Compile Include="Binders\Json\MvxJsonBindingDescription.cs" />
<Compile Include="Binders\Json\MvxJsonBindingDescriptionParser.cs" />
<Compile Include="Binders\Json\MvxJsonBindingParser.cs" />
<Compile Include="Binders\Json\MvxJsonBindingSpecification.cs" />
<Compile Include="Binders\MvxFromTextBinder.cs" />
<Compile Include="Binders\MvxFullBinding.cs" />
<Compile Include="Binders\MvxStaticBasedValueConverterRegistryFiller.cs" />
<Compile Include="Binders\MvxValueConverterRegistry.cs" />
<Compile Include="Bindings\MvxBaseBinding.cs" />
<Compile Include="Bindings\MvxCompositeBinding.cs" />
<Compile Include="Bindings\Source\Construction\MvxSourceBindingFactory.cs" />
<Compile Include="Bindings\Source\MvxBasePropertyInfoSourceBinding.cs" />
<Compile Include="Bindings\Source\MvxBaseSourceBinding.cs" />
<Compile Include="Bindings\Source\MvxChainedSourceBinding.cs" />
<Compile Include="Bindings\Source\MvxDirectToSourceBinding.cs" />
<Compile Include="Bindings\Source\MvxPropertyInfoSourceBinding.cs" />
<Compile Include="Bindings\Target\Construction\MvxCustomBindingFactory.cs" />
<Compile Include="Bindings\Target\Construction\MvxPropertyInfoTargetBindingFactory.cs" />
<Compile Include="Bindings\Target\Construction\MvxSimplePropertyInfoTargetBindingFactory.cs" />
<Compile Include="Bindings\Target\Construction\MvxTargetBindingFactoryRegistry.cs" />
<Compile Include="Bindings\Target\MvxBaseTargetBinding.cs" />
<Compile Include="Bindings\Target\MvxEventHandlerEventInfoTargetBinding.cs" />
<Compile Include="Bindings\Target\MvxEventInfoTargetBinding.cs" />
<Compile Include="Bindings\Target\MvxNullTargetBinding.cs" />
<Compile Include="Bindings\Target\MvxPropertyInfoTargetBinding.cs" />
<Compile Include="Interfaces\Binders\IMvxBindingDescriptionParser.cs" />
<Compile Include="Interfaces\Binders\IMvxValueConverterProvider.cs" />
<Compile Include="Interfaces\Binders\IMvxValueConverterRegistry.cs" />
<Compile Include="Interfaces\Bindings\Source\Construction\IMvxSourceBindingFactory.cs" />
<Compile Include="Interfaces\Bindings\Source\IMvxSourceBinding.cs" />
<Compile Include="Interfaces\Bindings\Source\MvxSourcePropertyBindingEventArgs.cs" />
<Compile Include="Interfaces\Bindings\Target\Construction\IMvxPluginTargetBindingFactory.cs" />
<Compile Include="Interfaces\Bindings\Target\Construction\IMvxTargetBindingFactory.cs" />
<Compile Include="Interfaces\Bindings\Target\Construction\IMvxTargetBindingFactoryRegistry.cs" />
<Compile Include="Interfaces\Bindings\Target\Construction\MvxTypeAndNamePair.cs" />
<Compile Include="Interfaces\Bindings\Target\IMvxTargetBinding.cs" />
<Compile Include="Interfaces\Bindings\Target\MvxTargetChangedEventArgs.cs" />
<Compile Include="Interfaces\IMvxBinder.cs" />
<Compile Include="Interfaces\IMvxBinding.cs" />
<Compile Include="Interfaces\IMvxUpdateableBinding.cs" />
<Compile Include="Interfaces\MvxBindingDescription.cs" />
<Compile Include="Interfaces\MvxBindingMode.cs" />
<Compile Include="Interfaces\MvxBindingRequest.cs" />
<Compile Include="MvxBindingSetup.cs" />
<Compile Include="MvxBindingTrace.cs" />
<Compile Include="MvxBindingTraceLevel.cs" />
<Compile Include="Touch\MvxTouchBindingSetup.cs" />
<Compile Include="Touch\Interfaces\Views\IMvxBindableView.cs" />
<Compile Include="Touch\Views\MvxBindableTableViewCell.cs" />
<Compile Include="Touch\Views\MvxBindableTableViewDataSource.cs" />
<Compile Include="Touch\Views\MvxBindableTableViewDelegate.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Library\Dialog\MonoTouch.Dialog\MonoTouch.Dialog.csproj">
<Project>{3FFBFFF8-5560-4EDE-82E5-3FFDFBBA8A50}</Project>
<Name>MonoTouch.Dialog</Name>
</ProjectReference>
<ProjectReference Include="..\..\Library\Newtonsoft.Json\Newtonsoft.Json\Newtonsoft_Json_MonoTouch.csproj">
<Project>{7E04C0C7-C26E-4F5E-A634-A687757E76A1}</Project>
<Name>Newtonsoft_Json_MonoTouch</Name>
</ProjectReference>
<ProjectReference Include="..\Cirrious.MvvmCross\Cirrious.MvvmCross.Touch.csproj">
<Project>{E042EDD9-E89D-4928-BF4D-27F0FC29CEDA}</Project>
<Name>Cirrious.MvvmCross.Touch</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<CodeAnalysisDictionary Include="ResourcesToCopy\MvxBindingAttributes.xml" />
</ItemGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Cirrious.MvvmCross.Binding.Interfaces.Binders
{
public interface IMvxBindingDescriptionParser
{
IEnumerable<MvxBindingDescription> Parse(string text);
}
}

Просмотреть файл

@ -0,0 +1,9 @@
using Cirrious.MvvmCross.Interfaces.Converters;
namespace Cirrious.MvvmCross.Binding.Interfaces.Binders
{
public interface IMvxValueConverterProvider
{
IMvxValueConverter Find(string converterName);
}
}

Просмотреть файл

@ -0,0 +1,9 @@
using Cirrious.MvvmCross.Interfaces.Converters;
namespace Cirrious.MvvmCross.Binding.Interfaces.Binders
{
public interface IMvxValueConverterRegistry
{
void AddOrOverwrite(string name, IMvxValueConverter converter);
}
}

Просмотреть файл

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source.Construction
{
public interface IMvxSourceBindingFactory
{
IMvxSourceBinding CreateBinding(object source, string combinedPropertyName);
IMvxSourceBinding CreateBinding(object source, IEnumerable<string> childPropertyNames);
}
}

Просмотреть файл

@ -0,0 +1,12 @@
using System;
namespace Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source
{
public interface IMvxSourceBinding : IMvxBinding
{
void SetValue(object value);
Type SourceType { get; }
event EventHandler<MvxSourcePropertyBindingEventArgs> Changed;
bool TryGetValue(out object value);
}
}

Просмотреть файл

@ -0,0 +1,30 @@
using System;
namespace Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source
{
public class MvxSourcePropertyBindingEventArgs : EventArgs
{
private readonly bool _isAvailable;
public bool IsAvailable
{
get { return _isAvailable; }
}
private readonly object _value;
public object Value
{
get { return _value; }
}
public MvxSourcePropertyBindingEventArgs(bool isAvailable, Object value)
{
_isAvailable = isAvailable;
_value = value;
}
public MvxSourcePropertyBindingEventArgs(IMvxSourceBinding propertySourceBinding)
{
_isAvailable = propertySourceBinding.TryGetValue(out _value);
}
}
}

Просмотреть файл

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction
{
public interface IMvxPluginTargetBindingFactory : IMvxTargetBindingFactory
{
IEnumerable<MvxTypeAndNamePair> SupportedTypes { get; }
}
}

Просмотреть файл

@ -0,0 +1,7 @@
namespace Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction
{
public interface IMvxTargetBindingFactory
{
IMvxTargetBinding CreateBinding(object target, MvxBindingDescription description);
}
}

Просмотреть файл

@ -0,0 +1,7 @@
namespace Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction
{
public interface IMvxTargetBindingFactoryRegistry : IMvxTargetBindingFactory
{
void RegisterFactory(IMvxPluginTargetBindingFactory factory);
}
}

Просмотреть файл

@ -0,0 +1,20 @@
using System;
namespace Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction
{
public class MvxTypeAndNamePair
{
public Type Type { get; set; }
public string Name { get; set; }
public MvxTypeAndNamePair()
{
}
public MvxTypeAndNamePair(Type type, string name)
{
Type = type;
Name = name;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
using System;
namespace Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target
{
public interface IMvxTargetBinding : IMvxBinding
{
void SetValue(object value);
Type TargetType { get; }
event EventHandler<MvxTargetChangedEventArgs> ValueChanged;
MvxBindingMode DefaultMode { get; }
}
}

Просмотреть файл

@ -0,0 +1,15 @@
using System;
namespace Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target
{
public class MvxTargetChangedEventArgs
: EventArgs
{
public Object Value { get; private set; }
public MvxTargetChangedEventArgs(object value)
{
Value = value;
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace Cirrious.MvvmCross.Binding.Interfaces
{
public interface IMvxBinder
{
IMvxUpdateableBinding Bind(MvxBindingRequest bindingRequest);
IEnumerable<IMvxUpdateableBinding> Bind(object source, object target, string bindingText);
IEnumerable<IMvxUpdateableBinding> Bind(object source, object target,
IEnumerable<MvxBindingDescription> bindingDescriptions);
}
}

Просмотреть файл

@ -0,0 +1,8 @@
using System;
namespace Cirrious.MvvmCross.Binding.Interfaces
{
public interface IMvxBinding : IDisposable
{
}
}

Просмотреть файл

@ -0,0 +1,7 @@
namespace Cirrious.MvvmCross.Binding.Interfaces
{
public interface IMvxUpdateableBinding : IMvxBinding
{
object DataContext { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,33 @@
using Cirrious.MvvmCross.Interfaces.Converters;
namespace Cirrious.MvvmCross.Binding.Interfaces
{
public class MvxBindingDescription
{
public MvxBindingDescription()
{
}
public MvxBindingDescription(string targetName, string sourcePropertyPath, IMvxValueConverter converter, object converterParameter, object fallbackValue, MvxBindingMode mode)
{
TargetName = targetName;
SourcePropertyPath = sourcePropertyPath;
Converter = converter;
ConverterParameter = converterParameter;
FallbackValue = fallbackValue;
Mode = mode;
}
public string TargetName { get; set; }
public string SourcePropertyPath { get; set; }
public IMvxValueConverter Converter { get; set; }
public object ConverterParameter { get; set; }
public object FallbackValue { get; set; }
public MvxBindingMode Mode { get; set; }
public override string ToString()
{
return string.Format("from {0} to {1}", SourcePropertyPath, TargetName);
}
}
}

Просмотреть файл

@ -0,0 +1,11 @@
namespace Cirrious.MvvmCross.Binding.Interfaces
{
public enum MvxBindingMode
{
Default = 0,
TwoWay,
OneWay,
OneTime,
OneWayToSource
}
}

Просмотреть файл

@ -0,0 +1,20 @@
namespace Cirrious.MvvmCross.Binding.Interfaces
{
public class MvxBindingRequest
{
public MvxBindingRequest()
{
}
public MvxBindingRequest(object source, object target, MvxBindingDescription description)
{
Target = target;
Source = source;
Description = description;
}
public object Target { get; set; }
public object Source { get; set; }
public MvxBindingDescription Description { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,82 @@
using Cirrious.MvvmCross.Binding.Binders;
using Cirrious.MvvmCross.Binding.Binders.Json;
using Cirrious.MvvmCross.Binding.Bindings.Source.Construction;
using Cirrious.MvvmCross.Binding.Bindings.Target.Construction;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Binders;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Source.Construction;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.Converters;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
namespace Cirrious.MvvmCross.Binding
{
public class MvxBindingSetup
: IMvxServiceProducer<IMvxTargetBindingFactoryRegistry>
, IMvxServiceProducer<IMvxTargetBindingFactory>
, IMvxServiceProducer<IMvxSourceBindingFactory>
, IMvxServiceProducer<IMvxValueConverterRegistry>
, IMvxServiceProducer<IMvxValueConverterProvider>
, IMvxServiceProducer<IMvxBinder>
, IMvxServiceProducer<IMvxBindingDescriptionParser>
{
public virtual void DoRegistration()
{
RegisterCore();
RegisterSourceFactory();
RegisterTargetFactory();
RegisterValueConverterProvider();
RegisterBindingParametersParser();
RegisterPlatformSpecificComponents();
}
protected virtual void RegisterCore()
{
var binder = new MvxFromTextBinder();
this.RegisterServiceInstance<IMvxBinder>(binder);
}
protected virtual void RegisterSourceFactory()
{
var sourceFactory = new MvxSourceBindingFactory();
this.RegisterServiceInstance<IMvxSourceBindingFactory>(sourceFactory);
}
protected virtual void RegisterTargetFactory()
{
var targetRegistry = new MvxTargetBindingFactoryRegistry();
this.RegisterServiceInstance<IMvxTargetBindingFactoryRegistry>(targetRegistry);
this.RegisterServiceInstance<IMvxTargetBindingFactory>(targetRegistry);
FillTargetFactories(targetRegistry);
}
protected virtual void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
// base class has nothing to register
}
protected virtual void RegisterValueConverterProvider()
{
var registry = new MvxValueConverterRegistry();
this.RegisterServiceInstance<IMvxValueConverterRegistry>(registry);
this.RegisterServiceInstance<IMvxValueConverterProvider>(registry);
FillValueConverters(registry);
}
protected virtual void FillValueConverters(IMvxValueConverterRegistry registry)
{
// nothing to do here
}
protected virtual void RegisterBindingParametersParser()
{
this.RegisterServiceInstance<IMvxBindingDescriptionParser>(new MvxJsonBindingDescriptionParser());
}
protected virtual void RegisterPlatformSpecificComponents()
{
// nothing to do here
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
using Cirrious.MvvmCross.Platform.Diagnostics;
namespace Cirrious.MvvmCross.Binding
{
public static class MvxBindingTrace
{
public static MvxBindingTraceLevel Level = MvxBindingTraceLevel.Warning;
public const string Tag = "MvxBind";
public static void Trace(MvxBindingTraceLevel level, string message, params object[] args)
{
if (level >= Level)
MvxTrace.TaggedTrace(Tag, message, args);
}
}
}

Просмотреть файл

@ -0,0 +1,9 @@
namespace Cirrious.MvvmCross.Binding
{
public enum MvxBindingTraceLevel
{
Diagnostic,
Warning,
Error
}
}

Просмотреть файл

@ -0,0 +1,29 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Cirrious.MvvmCross.Binding.Android")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Cirrious.MvvmCross.Binding.Android")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MvxBinding">
<attr name="MvxBind" format="string"/>
</declare-styleable>
<declare-styleable name="MvxBindableListView">
<attr name="MvxItemTemplate" format="string"/>
</declare-styleable>
<item type="id" name="MvxBindingTagUnique"/>
<item type="id" name="MvxBindableListItemTagUnique"/>
</resources>

Просмотреть файл

@ -0,0 +1,7 @@
namespace Cirrious.MvvmCross.Binding.Touch.Views
{
public interface IMvxBindableView
{
void BindTo(object source);
}
}

Просмотреть файл

@ -0,0 +1,27 @@
using Cirrious.MvvmCross.Binding.Bindings.Source.Construction;
using Cirrious.MvvmCross.Binding.Bindings.Target.Construction;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
namespace Cirrious.MvvmCross.Binding.Touch
{
public class MvxTouchBindingSetup
: MvxBindingSetup
{
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
// TODO - are there any special targets for Touch?
base.FillTargetFactories(registry);
}
protected override void RegisterPlatformSpecificComponents()
{
// TODO - are there any special platform specific components for Touch?
base.RegisterPlatformSpecificComponents();
}
}
}

Просмотреть файл

@ -0,0 +1,68 @@
using System.Collections.Generic;
using System.Linq;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace Cirrious.MvvmCross.Binding.Touch.Views
{
public class MvxBindableTableViewCell
: UITableViewCell
, IMvxBindableView
, IMvxServiceConsumer<IMvxBinder>
{
private readonly IList<IMvxUpdateableBinding> _bindings;
private IMvxBinder Binder
{
get { return this.GetService<IMvxBinder>(); }
}
public MvxBindableTableViewCell(string bindingText, UITableViewCellStyle cellStyle, NSString cellIdentifier)
: base(cellStyle, cellIdentifier)
{
_bindings = Binder.Bind(null, this, bindingText).ToList();
}
public MvxBindableTableViewCell(IEnumerable<MvxBindingDescription> bindingDescriptions, UITableViewCellStyle cellStyle, NSString cellIdentifier)
: base(cellStyle, cellIdentifier)
{
_bindings = Binder.Bind(null, this, bindingDescriptions).ToList();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
foreach (var binding in _bindings)
{
binding.Dispose();
}
_bindings.Clear();
}
base.Dispose(disposing);
}
public void BindTo(object source)
{
foreach (var binding in _bindings)
{
binding.DataContext = source;
}
}
public string TitleText
{
get { return TextLabel.Text; }
set { TextLabel.Text = value; }
}
public string DetailText
{
get { return DetailTextLabel.Text; }
set { DetailTextLabel.Text = value; }
}
}
}

Просмотреть файл

@ -0,0 +1,72 @@
using System.Collections;
using System.Collections.Specialized;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace Cirrious.MvvmCross.Binding.Touch.Views
{
public abstract class MvxBindableTableViewDataSource : UITableViewDataSource
{
private readonly UITableView _tableView;
protected MvxBindableTableViewDataSource(UITableView tableView)
{
_tableView = tableView;
}
private IList _itemsSource;
public IList ItemsSource
{
get { return _itemsSource; }
set
{
if (_itemsSource == value)
return;
var collectionChanged = _itemsSource as INotifyCollectionChanged;
if (collectionChanged != null)
collectionChanged.CollectionChanged -= CollectionChangedOnCollectionChanged;
_itemsSource = value;
collectionChanged = _itemsSource as INotifyCollectionChanged;
if (collectionChanged != null)
collectionChanged.CollectionChanged += CollectionChangedOnCollectionChanged;
_tableView.ReloadData();
}
}
private void CollectionChangedOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
{
_tableView.ReloadData();
}
public override int RowsInSection(UITableView tableview, int section)
{
if (ItemsSource == null)
return 0;
return ItemsSource.Count;
}
protected abstract UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item);
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
if (ItemsSource == null)
return null;
var item = ItemsSource[indexPath.Row];
var cell = GetOrCreateCellFor(tableView, indexPath, item);
var bindable = cell as IMvxBindableView;
if (bindable != null)
bindable.BindTo(item);
return cell;
}
public override int NumberOfSections(UITableView tableView)
{
return 1;
}
}
}

Просмотреть файл

@ -0,0 +1,27 @@
using System;
using System.Collections;
using Cirrious.MvvmCross.Commands;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace Cirrious.MvvmCross.Binding.Touch.Views
{
public class MvxBindableTableViewDelegate : UITableViewDelegate
{
public IList ItemsSource { get; set; }
public event EventHandler<MvxSimpleSelectionChangedEventArgs> SelectionChanged;
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
if (ItemsSource == null)
return;
var item = ItemsSource[indexPath.Row];
var selectionChangedArgs = MvxSimpleSelectionChangedEventArgs.JustAddOneItem(item);
var handler = SelectionChanged;
if (handler != null)
handler(this, selectionChangedArgs);
}
}
}

Просмотреть файл

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{5AB67AC7-5C93-4F55-B76D-0F6E4D822D4A}</ProjectGuid>
<ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Cirrious.MvvmCross.Touch.Dialog</RootNamespace>
<AssemblyName>Cirrious.MvvmCross.Dialog.Touch</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<AssemblyName>Cirrious.MvvmCross.Dialog.Touch</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<AssemblyName>Cirrious.MvvmCross.Dialog.Touch</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AdHoc|iPhone' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\iPhone\AdHoc</OutputPath>
<WarningLevel>4</WarningLevel>
<AssemblyName>CirriousMvvmCrossDialogTouch</AssemblyName>
<CodesignKey>iPhone Developer</CodesignKey>
<DefineConstants>MONOTOUCH</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|iPhone'">
<OutputPath>bin\iPhone\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|iPhone'">
<OutputPath>bin\iPhone\Release\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="monotouch">
<HintPath>..\..\Library\Hacked\monotouch.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Compile Include="MvxTouchDialogViewController.cs" />
<Compile Include="MvxTouchDialogViewControllerBinderExtensions.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Library\Dialog\MonoTouch.Dialog\MonoTouch.Dialog.csproj">
<Project>{3FFBFFF8-5560-4EDE-82E5-3FFDFBBA8A50}</Project>
<Name>MonoTouch.Dialog</Name>
</ProjectReference>
<ProjectReference Include="..\Cirrious.MvvmCross.Binding\Cirrious.MvvmCross.Binding.Touch.csproj">
<Project>{062250C5-A896-4FCF-AA34-7F2C370E682B}</Project>
<Name>Cirrious.MvvmCross.Binding.Touch</Name>
</ProjectReference>
<ProjectReference Include="..\Cirrious.MvvmCross\Cirrious.MvvmCross.Touch.csproj">
<Project>{E042EDD9-E89D-4928-BF4D-27F0FC29CEDA}</Project>
<Name>Cirrious.MvvmCross.Touch</Name>
</ProjectReference>
</ItemGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,115 @@
#region Copyright
// <copyright file="MvxTouchDialogViewController.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>
//
// Author - Stuart Lodge, Cirrious. http://www.cirrious.com
#endregion
using System;
using System.Collections.Generic;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Touch.ExtensionMethods;
using Cirrious.MvvmCross.Touch.Interfaces;
using Cirrious.MvvmCross.Interfaces.ViewModels;
using Cirrious.MvvmCross.Touch.Views;
using Cirrious.MvvmCross.Views;
using MonoTouch.UIKit;
using MonoTouch.Dialog;
namespace Cirrious.MvvmCross.Touch.Dialog
{
public class MvxTouchDialogViewController<TViewModel>
: DialogViewController
, IMvxTouchView<TViewModel>
where TViewModel : class, IMvxViewModel
{
private readonly List<IMvxBinding> _bindings = new List<IMvxBinding>();
protected MvxTouchDialogViewController(MvxShowViewModelRequest request, UITableViewStyle style, RootElement root, bool pushing)
: base(style, root, pushing)
{
ShowRequest = request;
}
public void AddBindings(IEnumerable<IMvxBinding> bindings)
{
_bindings.AddRange(bindings);
}
public void AddBinding(IMvxBinding binding)
{
_bindings.Add(binding);
}
#region Shared code across all Touch ViewControllers
public bool IsVisible { get { return this.IsVisible(); } }
private TViewModel _viewModel;
public TViewModel ViewModel
{
get { return _viewModel; }
set
{
_viewModel = value;
OnViewModelChanged();
}
}
public MvxTouchViewDisplayType DisplayType { get { return MvxTouchViewDisplayType.Master; } }
public Type ViewModelType
{
get { return typeof(TViewModel); }
}
protected virtual void OnViewModelChanged() { }
public override void DismissViewController(bool animated, MonoTouch.Foundation.NSAction completionHandler)
{
base.DismissViewController(animated, completionHandler);
#warning Not sure about positioning of Create/Destory here...
this.OnViewDestroy();
}
public override void ViewDidLoad()
{
#warning Not sure about positioning of Create/Destory here...
this.OnViewCreate();
base.ViewDidLoad();
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
}
public override void ViewDidDisappear(bool animated)
{
base.ViewDidDisappear(animated);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
// note that Dispose(true) should be called on the UI thread so we remain thread safe here
_bindings.ForEach(x => x.Dispose());
_bindings.Clear();
}
base.Dispose(disposing);
}
public MvxShowViewModelRequest ShowRequest { get; private set; }
#endregion
}
}

Просмотреть файл

@ -0,0 +1,27 @@
using System.Collections.Generic;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ViewModels;
using MonoTouch.Dialog;
namespace Cirrious.MvvmCross.Touch.Dialog
{
public static class MvxTouchDialogViewControllerBinderExtensions
{
public static Element Bind<TViewModel>(this Element element, MvxTouchDialogViewController<TViewModel> controller, string descriptionText)
where TViewModel : class, IMvxViewModel
{
var binder = MvxServiceProviderExtensions.GetService<IMvxBinder>();
controller.AddBindings(binder.Bind(controller.ViewModel, element, descriptionText));
return element;
}
public static Element Bind<TViewModel>(this Element element, MvxTouchDialogViewController<TViewModel> controller, IEnumerable<MvxBindingDescription> descriptions)
where TViewModel : class, IMvxViewModel
{
var binder = MvxServiceProviderExtensions.GetService<IMvxBinder>();
controller.AddBindings(binder.Bind(controller.ViewModel, element, descriptions));
return element;
}
}
}

Просмотреть файл

@ -0,0 +1,29 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Cirrious.MvvmCross.Dialog")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Cirrious.MvvmCross.Dialog")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -11,46 +11,74 @@
#endregion
using System;
using Android.App;
using Cirrious.MvvmCross.Android.Interfaces;
using Cirrious.MvvmCross.Android.LifeTime;
using Cirrious.MvvmCross.Android.Views;
using Cirrious.MvvmCross.Exceptions;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ViewModel;
using Cirrious.MvvmCross.Interfaces.ViewModels;
using Cirrious.MvvmCross.Interfaces.Views;
using Cirrious.MvvmCross.ViewModels;
using Cirrious.MvvmCross.Views;
namespace Cirrious.MvvmCross.Android.ExtensionMethods
{
internal static class MvxAndroidActivityExtensionMethods
public static class MvxAndroidActivityExtensionMethods
{
public static void OnViewCreate<TViewModel>(this IMvxAndroidView<TViewModel> androidView)
where TViewModel : class, IMvxViewModel
{
if (androidView.ViewModel != null)
return;
androidView.OnLifetimeEvent((listener, activity) => listener.OnCreate(activity));
var viewModel = GetViewModel(androidView);
UpdateActivityTracker(androidView, viewModel);
androidView.SetViewModel(viewModel);
var view = androidView as IMvxTrackedView<TViewModel>;
view.OnViewCreate(() => { return androidView.LoadViewModel(); });
}
private static void UpdateActivityTracker<TViewModel>(IMvxAndroidView<TViewModel> androidView,
IMvxViewModel viewModel)
public static void OnViewDestroy<TViewModel>(this IMvxAndroidView<TViewModel> androidView)
where TViewModel : class, IMvxViewModel
{
var activityTracker = androidView.GetService<IMvxAndroidActivityTracker>();
var activity = androidView.ToActivity();
switch (androidView.Role)
{
case MvxAndroidViewRole.TopLevelView:
activityTracker.OnTopLevelAndroidActivity(activity, viewModel);
break;
case MvxAndroidViewRole.SubView:
activityTracker.OnSubViewAndroidActivity(activity);
break;
default:
throw new MvxException("What on earth is a view with role {0}", androidView.Role);
}
androidView.OnLifetimeEvent((listener, activity) => listener.OnDestroy(activity));
var view = androidView as IMvxTrackedView<TViewModel>;
view.OnViewDestroy();
}
public static void OnViewStart<TViewModel>(this IMvxAndroidView<TViewModel> androidView)
where TViewModel : class, IMvxViewModel
{
androidView.OnLifetimeEvent((listener, activity) => listener.OnStart(activity));
}
public static void OnViewRestart<TViewModel>(this IMvxAndroidView<TViewModel> androidView)
where TViewModel : class, IMvxViewModel
{
androidView.OnLifetimeEvent((listener, activity) => listener.OnRestart(activity));
}
public static void OnViewStop<TViewModel>(this IMvxAndroidView<TViewModel> androidView)
where TViewModel : class, IMvxViewModel
{
androidView.OnLifetimeEvent((listener, activity) => listener.OnStop(activity));
}
public static void OnViewResume<TViewModel>(this IMvxAndroidView<TViewModel> androidView)
where TViewModel : class, IMvxViewModel
{
androidView.OnLifetimeEvent((listener, activity) => listener.OnResume(activity));
}
public static void OnViewPause<TViewModel>(this IMvxAndroidView<TViewModel> androidView)
where TViewModel : class, IMvxViewModel
{
androidView.OnLifetimeEvent((listener, activity) => listener.OnPause(activity));
}
private static void OnLifetimeEvent<TViewModel>(this IMvxAndroidView<TViewModel> androidView, Action<IMvxAndroidActivityLifetimeListener, Activity> report)
where TViewModel : class, IMvxViewModel
{
var activityTracker = androidView.GetService<IMvxAndroidActivityLifetimeListener>();
report(activityTracker, androidView.ToActivity());
}
public static Activity ToActivity<TViewModel>(this IMvxAndroidView<TViewModel> androidView)
@ -62,28 +90,13 @@ namespace Cirrious.MvvmCross.Android.ExtensionMethods
return activity;
}
private static IMvxViewModel GetViewModel<TViewModel>(IMvxAndroidView<TViewModel> androidView)
where TViewModel : class, IMvxViewModel
{
IMvxViewModel viewModel;
switch (androidView.Role)
{
case MvxAndroidViewRole.TopLevelView:
viewModel = GetViewModelForTopLevelView(androidView);
break;
case MvxAndroidViewRole.SubView:
viewModel = GetViewModelForSubView(androidView);
break;
default:
throw new MvxException("What on earth is a view with role {0}", androidView.Role);
}
return viewModel;
}
private static IMvxViewModel GetViewModelForTopLevelView<TViewModel>(IMvxAndroidView<TViewModel> androidView)
private static TViewModel LoadViewModel<TViewModel>(this IMvxAndroidView<TViewModel> androidView)
where TViewModel : class, IMvxViewModel
{
var activity = androidView.ToActivity();
if (typeof(TViewModel) == typeof(MvxNullViewModel))
return new MvxNullViewModel() as TViewModel;
var translatorService = androidView.GetService<IMvxAndroidViewModelRequestTranslator>();
var viewModelRequest = translatorService.GetRequestFromIntent(activity.Intent);
@ -92,15 +105,7 @@ namespace Cirrious.MvvmCross.Android.ExtensionMethods
var loaderService = androidView.GetService<IMvxViewModelLoader>();
var viewModel = loaderService.LoadModel(viewModelRequest);
return viewModel;
}
private static IMvxViewModel GetViewModelForSubView<TViewModel>(IMvxAndroidView<TViewModel> androidView)
where TViewModel : class, IMvxViewModel
{
var activityServices = androidView.GetService<IMvxAndroidSubViewServices>();
var viewModel = activityServices.CurrentTopLevelViewModel;
return viewModel;
return (TViewModel)viewModel;
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
using Android.App;
namespace Cirrious.MvvmCross.Android.Interfaces
{
public interface IMvxAndroidActivityLifetimeListener
{
void OnCreate(Activity activity);
void OnStart(Activity activity);
void OnRestart(Activity activity);
void OnResume(Activity activity);
void OnPause(Activity activity);
void OnStop(Activity activity);
void OnDestroy(Activity activity);
}
}

Просмотреть файл

@ -0,0 +1,9 @@
using Android.Content;
namespace Cirrious.MvvmCross.Android.Platform
{
public interface IMvxAndroidContextSource
{
Context Context { get; }
}
}

Просмотреть файл

@ -0,0 +1,9 @@
using Android.App;
namespace Cirrious.MvvmCross.Android.Interfaces
{
public interface IMvxAndroidCurrentTopActivity
{
Activity Activity { get; }
}
}

Просмотреть файл

@ -0,0 +1,12 @@
using System.Reflection;
using Android.Content;
namespace Cirrious.MvvmCross.Android.Interfaces
{
public interface IMvxAndroidGlobals
{
string ExecutableNamespace { get; }
Assembly ExecutableAssembly { get; }
Context ApplicationContext { get; }
}
}

Просмотреть файл

@ -11,22 +11,31 @@
#endregion
using System;
using Android.Content;
using Cirrious.MvvmCross.Android.LifeTime;
using Cirrious.MvvmCross.Android.Views;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using Cirrious.MvvmCross.Interfaces.ViewModel;
using Cirrious.MvvmCross.Interfaces.ViewModels;
using Cirrious.MvvmCross.Interfaces.Views;
namespace Cirrious.MvvmCross.Android.Interfaces
{
public interface IMvxAndroidView
: IMvxTrackedView
{
void MvxInternalStartActivityForResult(Intent intent, int requestCode);
event EventHandler<MvxIntentResultEventArgs> MvxIntentResultReceived;
}
public interface IMvxAndroidView<TViewModel>
: IMvxView
, IMvxServiceConsumer<IMvxViewModelLoader>
, IMvxServiceConsumer<IMvxAndroidViewModelRequestTranslator>
, IMvxServiceConsumer<IMvxAndroidActivityTracker>
, IMvxServiceConsumer<IMvxAndroidSubViewServices>
: IMvxTrackedView<TViewModel>
, IMvxAndroidView
, IMvxServiceConsumer<IMvxViewModelLoader>
, IMvxServiceConsumer<IMvxAndroidViewModelRequestTranslator>
, IMvxServiceConsumer<IMvxAndroidActivityLifetimeListener>
where TViewModel : class, IMvxViewModel
{
TViewModel ViewModel { get; set; }
MvxAndroidViewRole Role { get; }
new TViewModel ViewModel { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,9 @@
namespace Cirrious.MvvmCross.Android.Interfaces
{
public enum MvxIntentRequestCode
: int
{
PickFromFile = 30001,
PickFromCamera = 30002
}
}

Просмотреть файл

@ -0,0 +1,21 @@
using System;
using Android.App;
using Android.Content;
namespace Cirrious.MvvmCross.Android.Interfaces
{
public class MvxIntentResultEventArgs
: EventArgs
{
public MvxIntentResultEventArgs(int requestCode, Result resultCode, Intent data)
{
Data = data;
ResultCode = resultCode;
RequestCode = requestCode;
}
public int RequestCode { get; private set; }
public Result ResultCode { get; private set; }
public Intent Data { get; private set; }
}
}

Просмотреть файл

@ -11,8 +11,10 @@
#endregion
using System.Reflection;
using Android.Content;
using Cirrious.MvvmCross.Android.Interfaces;
using Cirrious.MvvmCross.Android.Services;
using Cirrious.MvvmCross.Android.Views;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
@ -23,24 +25,33 @@ namespace Cirrious.MvvmCross.Android.Platform
{
public abstract class MvxBaseAndroidSetup
: MvxBaseSetup
, IMvxServiceProducer<IMvxAndroidViewModelRequestTranslator>
, IMvxServiceProducer<IMvxAndroidSubViewServices>
, IMvxServiceProducer<IMvxAndroidActivityTracker>
, IMvxAndroidGlobals
, IMvxServiceProducer<IMvxAndroidViewModelRequestTranslator>
, IMvxServiceProducer<IMvxAndroidContextSource>
, IMvxServiceProducer<IMvxAndroidGlobals>
{
private readonly Context _applicationContext;
protected MvxBaseAndroidSetup(Context applicationContext)
{
_applicationContext = applicationContext;
_applicationContext = applicationContext;
}
protected override void InitializeAdditionalPlatformServices()
{
MvxAndroidServiceProvider.Instance.RegisterPlatformContextTypes(_applicationContext);
this.RegisterServiceInstance<IMvxAndroidGlobals>(this);
}
protected override MvxViewsContainer CreateViewsContainer()
{
var container = new MvxAndroidViewsContainer(_applicationContext);
this.RegisterServiceInstance<IMvxAndroidViewModelRequestTranslator>(container);
this.RegisterServiceInstance<IMvxAndroidSubViewServices>(container);
this.RegisterServiceInstance<IMvxAndroidActivityTracker>(container);
return container;
}
public abstract string ExecutableNamespace { get; }
public abstract Assembly ExecutableAssembly { get; }
public Context ApplicationContext { get { return _applicationContext; } }
}
}

Просмотреть файл

@ -0,0 +1,184 @@
#warning Credit to ChrisNTR fro some of this code
using System;
using System.Threading;
using Android.App;
using Android.Content;
using Android.Locations;
using Android.OS;
using Cirrious.MvvmCross.Android.Interfaces;
using Cirrious.MvvmCross.Exceptions;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using Cirrious.MvvmCross.Interfaces.Services.Location;
using Cirrious.MvvmCross.Platform;
using Cirrious.MvvmCross.Platform.Diagnostics;
namespace Cirrious.MvvmCross.Android.Services.Location
{
public sealed class MvxAndroidGeoLocationWatcher
: MvxBaseGeoLocationWatcher
, ILocationListener
, IMvxServiceConsumer<IMvxAndroidGlobals>
{
private LocationManager _locationManager;
private Context _context;
private Context Context
{
get
{
if (_context == null)
{
_context = this.GetService<IMvxAndroidGlobals>().ApplicationContext;
}
return _context;
}
}
public MvxAndroidGeoLocationWatcher()
{
EnsureStopped();
}
protected override void PlatformSpecificStart(MvxGeoLocationOptions options)
{
if (_locationManager != null)
throw new MvxException("You cannot start the MvxLocation service more than once");
_locationManager = (LocationManager)Context.GetSystemService(Context.LocationService);
var criteria = new Criteria() { Accuracy = options.EnableHighAccuracy ? Accuracy.Fine : Accuracy.Coarse };
var bestProvider = _locationManager.GetBestProvider(criteria, true);
_locationManager.RequestLocationUpdates(bestProvider, 5000, 2, this);
#warning _geoWatcher.MovementThreshold needed too
}
protected override void PlatformSpecificStop()
{
EnsureStopped();
}
private void EnsureStopped()
{
if (_locationManager != null)
{
_locationManager.RemoveUpdates(this);
_locationManager = null;
}
}
private static MvxGeoLocation CreateLocation(global::Android.Locations.Location androidLocation)
{
var position = new MvxGeoLocation { Timestamp = androidLocation.Time.FromMillisecondsUnixTimeToUtc() };
var coords = position.Coordinates;
#warning should some of these coords fields be nullable?
if (androidLocation.HasAltitude)
coords.Altitude = androidLocation.Altitude;
#warning MONODROID BUG WORKAROUND!
#warning MONODROID BUG WORKAROUND!
#warning MONODROID BUG WORKAROUND!
#warning MONODROID BUG WORKAROUND!
#warning MONODROID BUG WORKAROUND!
#warning MONODROID BUG WORKAROUND!
#warning MONODROID BUG WORKAROUND!
#warning MONODROID BUG WORKAROUND!
#warning MONODROID BUG WORKAROUND!
#warning MONODROID BUG WORKAROUND!
#warning MONODROID BUG WORKAROUND!
var testString = androidLocation.ToString();
coords.Latitude = HackReadValue(testString, "mLatitude=");
coords.Longitude = HackReadValue(testString, "mLongitude=");
return position;
/*
coords.Latitude = androidLocation.Latitude;
coords.Longitude = androidLocation.Longitude;
if (androidLocation.HasSpeed)
coords.Speed = androidLocation.Speed;
if (androidLocation.HasAccuracy)
{
coords.Accuracy = androidLocation.Accuracy;
}
#warning what to do with coords.AltitudeAccuracy ?S
//coords.AltitudeAccuracy = androidLocation.Accuracy;
return position;
*/
}
private static double HackReadValue(string testString, string key)
{
var startIndex = testString.IndexOf(key);
var endIndex = testString.IndexOf(",", startIndex);
var startPosition = startIndex + key.Length;
var toParse = testString.Substring(startPosition, endIndex - startPosition);
var value = double.Parse(toParse, System.Globalization.CultureInfo.InvariantCulture);
return value;
}
#region Implementation of ILocationListener
public void OnLocationChanged(global::Android.Locations.Location androidLocation)
{
if (androidLocation == null)
{
MvxTrace.Trace("Android: Null location seen");
return;
}
if (androidLocation.Latitude == double.MaxValue
|| androidLocation.Longitude == double.MaxValue)
{
MvxTrace.Trace("Android: Invalid location seen");
return;
}
MvxGeoLocation location;
try
{
location = CreateLocation(androidLocation);
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception exception)
{
MvxTrace.Trace("Android: Exception seen in converting location " + exception.ToLongString());
return;
}
SendLocation(location);
}
public void OnProviderDisabled(string provider)
{
SendError(MvxLocationErrorCode.PositionUnavailable);
}
public void OnProviderEnabled(string provider)
{
// nothing to do
}
public void OnStatusChanged(string provider, Availability status, Bundle extras)
{
switch (status)
{
case Availability.Available:
break;
case Availability.OutOfService:
case Availability.TemporarilyUnavailable:
SendError(MvxLocationErrorCode.PositionUnavailable);
break;
default:
throw new ArgumentOutOfRangeException("status");
}
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,49 @@
#region Copyright
// <copyright file="MvxFileStoreService.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>
//
// Author - Stuart Lodge, Cirrious. http://www.cirrious.com
#endregion
#region using
using System.IO;
using Android.Content;
using Cirrious.MvvmCross.Android.Interfaces;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using Cirrious.MvvmCross.Platform;
#endregion
namespace Cirrious.MvvmCross.Android.Services
{
public class MvxAndroidFileStoreService
: MvxBaseFileStoreService
, IMvxServiceConsumer<IMvxAndroidGlobals>
{
private Context _context;
private Context Context
{
get
{
if (_context == null)
{
_context = this.GetService<IMvxAndroidGlobals>().ApplicationContext;
}
return _context;
}
}
protected override string FullPath(string path)
{
return Path.Combine(Context.FilesDir.Path, path);
}
}
}

Просмотреть файл

@ -0,0 +1,59 @@
#region Copyright
// <copyright file="MvxAndroidResourceLoader.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>
//
// Author - Stuart Lodge, Cirrious. http://www.cirrious.com
#endregion
using System;
using System.IO;
using Android.Content.Res;
using Cirrious.MvvmCross.Android.Interfaces;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.Localization;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using Cirrious.MvvmCross.Platform;
namespace Cirrious.MvvmCross.Android.Services
{
public class MvxAndroidResourceLoader
: MvxBaseResourceLoader
, IMvxServiceConsumer<IMvxAndroidGlobals>
{
private AssetManager _assets;
private AssetManager Assets
{
get
{
if (_assets == null)
{
_assets = this.GetService<IMvxAndroidGlobals>().ApplicationContext.Assets;
}
return _assets;
}
}
public MvxAndroidResourceLoader()
{
}
#region Implementation of IMvxResourceLoader
public override void GetResourceStream(string resourcePath, Action<Stream> streamAction)
{
#warning ? need to check and clarify what exceptions can be thrown here!
using (var input = Assets.Open(resourcePath))
{
streamAction(input);
}
}
#endregion
}
}

Просмотреть файл

@ -13,9 +13,16 @@
#region using
using Android.Content;
using Cirrious.MvvmCross.Android.Interfaces;
using Cirrious.MvvmCross.Android.LifeTime;
using Cirrious.MvvmCross.Android.Services.Location;
using Cirrious.MvvmCross.Android.Services.Tasks;
using Cirrious.MvvmCross.Interfaces.IoC;
using Cirrious.MvvmCross.Interfaces.Localization;
using Cirrious.MvvmCross.Interfaces.Services;
using Cirrious.MvvmCross.Interfaces.Services.Lifetime;
using Cirrious.MvvmCross.Interfaces.Services.Location;
using Cirrious.MvvmCross.Interfaces.Services.Tasks;
using Cirrious.MvvmCross.Platform;
@ -29,14 +36,41 @@ namespace Cirrious.MvvmCross.Android.Services
public override void Initialize(IMvxIoCProvider iocProvider)
{
base.Initialize(iocProvider);
SetupPlatformTypes();
RegisterPlatformTypes();
}
private void SetupPlatformTypes()
public static new MvxAndroidServiceProvider Instance
{
RegisterServiceType<IMvxSimpleFileStoreService, MvxFileStoreService>();
get { return (MvxAndroidServiceProvider)MvxPlatformIndependentServiceProvider.Instance; }
}
private void RegisterPlatformTypes()
{
RegisterServiceInstance<IMvxTrace>(new MvxDebugTrace());
RegisterServiceType<IMvxWebBrowserTask, MvxWebBrowserTask>();
RegisterServiceType<IMvxPhoneCallTask, MvxPhoneCallTask>();
var lifetimeMonitor = new MvxAndroidLifetimeMonitor();
RegisterServiceInstance<IMvxAndroidActivityLifetimeListener>(lifetimeMonitor);
RegisterServiceInstance<IMvxAndroidCurrentTopActivity>(lifetimeMonitor);
RegisterServiceInstance<IMvxLifetime>(lifetimeMonitor);
}
public void RegisterPlatformContextTypes(Context applicationContext)
{
RegisterServiceInstance<IMvxResourceLoader>(new MvxAndroidResourceLoader());
RegisterServiceInstance<IMvxSimpleFileStoreService>(new MvxAndroidFileStoreService());
RegisterServiceType<IMvxPictureChooserTask, MvxPictureChooserTask>();
#warning Would be nice if sound effects were optional so that not everyone has to link to xna!
#warning TODO - sound effects!
//var soundEffectLoader = new SoundEffects.MvxSoundEffectObjectLoader();
//RegisterServiceInstance<IMvxResourceObjectLoaderConfiguration<IMvxSoundEffect>>(soundEffectLoader);
//RegisterServiceInstance<IMvxResourceObjectLoader<IMvxSoundEffect>>(soundEffectLoader);
#warning Would be very nice if GPS were optional!
RegisterServiceInstance<IMvxGeoLocationWatcher>(new MvxAndroidGeoLocationWatcher());
}
}
}

Просмотреть файл

@ -11,6 +11,8 @@
#endregion
using System;
using System.Diagnostics;
using Cirrious.MvvmCross.Interfaces.Services;
namespace Cirrious.MvvmCross.Android.Services
@ -22,11 +24,21 @@ namespace Cirrious.MvvmCross.Android.Services
public void Trace(string tag, string message)
{
global::Android.Util.Log.Info(tag, message);
Debug.WriteLine(tag + ":" + message);
}
public void Trace(string tag, string message, params object[] args)
{
global::Android.Util.Log.Info(tag, message, args);
try
{
global::Android.Util.Log.Info(tag, message, args);
Debug.WriteLine(string.Format(tag + ":" + message, args));
}
catch (FormatException)
{
Trace(tag, "Exception during trace");
Trace(tag, message);
}
}
#endregion

Просмотреть файл

@ -0,0 +1,101 @@
#region Copyright
// <copyright file="MvxWindowsPhoneTask.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>
//
// Author - Stuart Lodge, Cirrious. http://www.cirrious.com
#endregion
using System;
using Android.App;
using Android.Content;
using Cirrious.MvvmCross.Android.Interfaces;
using Cirrious.MvvmCross.Exceptions;
using Cirrious.MvvmCross.ExtensionMethods;
using Cirrious.MvvmCross.Interfaces.ServiceProvider;
using Cirrious.MvvmCross.Interfaces.Views;
using Cirrious.MvvmCross.Platform.Diagnostics;
namespace Cirrious.MvvmCross.Android.Services.Tasks
{
public class MvxAndroidTask
: IMvxServiceConsumer<IMvxViewDispatcherProvider>
, IMvxServiceConsumer<IMvxAndroidCurrentTopActivity>
{
private IMvxViewDispatcher ViewDispatcher
{
get { return this.GetService<IMvxViewDispatcherProvider>().Dispatcher; }
}
private readonly Activity _owningActivity;
public MvxAndroidTask()
{
_owningActivity = this.GetService<IMvxAndroidCurrentTopActivity>().Activity;
}
protected void StartActivity(Intent intent)
{
DoOnActivity(activity => activity.StartActivity(intent));
}
protected void StartActivityForResult(int requestCode, Intent intent)
{
DoOnActivity(activity =>
{
var androidView = activity as IMvxAndroidView;
if (androidView == null)
{
MvxTrace.Trace("Error - current activity is null or does not support IMvxAndroidView");
return;
}
androidView.MvxIntentResultReceived += OnMvxIntentResultReceived;
androidView.MvxInternalStartActivityForResult(intent, requestCode);
});
}
protected virtual bool ProcessMvxIntentResult(MvxIntentResultEventArgs result)
{
// default processing does nothing
return false;
}
private void OnMvxIntentResultReceived(object sender, MvxIntentResultEventArgs e)
{
var androidView = sender as IMvxAndroidView;
if (androidView == null)
{
MvxTrace.Trace("Error - sender activity is null or does not support IMvxAndroidView");
return;
}
if (ProcessMvxIntentResult(e))
{
androidView.MvxIntentResultReceived -= OnMvxIntentResultReceived;
}
}
private void DoOnMainThread(Action action)
{
ViewDispatcher.RequestMainThreadAction(action);
}
private void DoOnActivity(Action<Activity> action, bool ensureOnMainThread = true)
{
if (ensureOnMainThread)
{
DoOnMainThread(() => action(_owningActivity));
}
else
{
action(_owningActivity);
}
}
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше