Attempt to get GitHub up to date again! Touch not tested through at present
This commit is contained in:
Родитель
8441502bc0
Коммит
78a0a236cd
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче