mvvmcross touch command binding in android - mvvm

I'm looking for a way to do a "Touch" command binding between axml and ViewModel, or some else like FocusChanged etc.
A simple "Click" command works fine like so:
local:MvxBind="{'Touch':{'Path':'CameraButtonCommand'}}" />
public IMvxCommand CameraButtonCommand
{
get
{
return new MvxRelayCommand(
() =>
{
RequestNavigate<AugRealityViewModel>(true);
})
;
}
}
However, I've tried other event types for the controll(in this case it's ImageButton) and they are not being processed. When I've checked the events listings in the View Class I see those:
public event EventHandler Click;
public event EventHandler<View.CreateContextMenuEventArgs> ContextMenuCreated;
public event EventHandler<View.FocusChangeEventArgs> FocusChange;
public event EventHandler<View.KeyEventArgs> KeyPress;
public event EventHandler<View.LongClickEventArgs> LongClick;
Only Click event has the general EventHandler attached to it, while other have genericed EventHandlers, and I'm wondering if that's the reason why it doesn't work.
I've also tried to attach a method to those events in the View class getting the proper control by FindViewById method and it works as expected this time around. But somehow I can't do it in the axml through Commands.
Also one more thing. The "Click" event is sending the "EventArgs" object as one of the parameters, and also the object reference. I can see that with ease if I do this behaviour in View Class, but when I do this by binding, I don't see those arguments when I'm processing the Command in ViewModel.

The framework can automatically bind any events which require EventHandler types. However, for any events which require a templated EventHandler (with custom EventArgs) then you are correct - you'll need to include a custom Binding.
The good news is that custom bindings are easy to write and to include.
For example, to bind:
public event EventHandler<View.LongClickEventArgs> LongClick;
you can include something like:
public class LongPressEventBinding
: MvxBaseAndroidTargetBinding
{
private readonly View _view;
private IMvxCommand _command;
public LongPressEventBinding(View view)
{
_view = view;
_view.LongClick += ViewOnLongClick;
}
private void ViewOnLongClick(object sender, View.LongClickEventArgs eventArgs)
{
if (_command != null)
{
_command.Execute();
}
}
public override void SetValue(object value)
{
_command = (IMvxCommand)value;
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
_view.Click -= ViewOnLongClick;
}
base.Dispose(isDisposing);
}
public override Type TargetType
{
get { return typeof(IMvxCommand); }
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.OneWay; }
}
}
Which can be configured in setup using something like:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterFactory(new MvxCustomBindingFactory<View>("LongPress", view => new LongPressEventBinding(view)));
}
Note that you can't write a single class that binds to all the different event types - as the compiler requires you to include the correct Type for the EventArgs. However, you could fairly easily change public class LongClickEventBinding to something like public class CustomEventBinding<TViewType, TEventArgsType> if you wanted to.
With regards to what argument you should pass into the IMvxCommand Execute method, I guess this depends a bit on the method in question, and it also depends on whether you need the ViewModel to support multiple platforms, or whether it is just for Android.

Related

this singleton has way can be improved?

i was using google's singleton but this must need too many reference.
example, when I have to use another class in my Player class that used singleton, I must be using reference three time. Like this : Player.instance.another.blank=0;
my singleton
public static Player instance;
public void Awake()
{
if(instance ==null){
instance=this;
}
else
{
if(instance!=this){
Destroy(this.gameObject);
}
}
Is there any reason to destroy the instance? Even so, we are not updating the existing instance immediately after destroying it whenever a player is added.
I have a singleton Gist that I usually use: https://gist.github.com/xepherys/34d3d5ce3f44749e8649a25b38127347
It has decent comments for anyone unfamiliar with singletons, and is threadsafe. You can remove everything except the lazy field and the constructor region. I use this as the basis for Manager classes.
using System;
// Update namespace as needed
namespace WhatsYourName
{
/*
This is the name of your threadsafe Singleton - change "SingletonLazyThreadsafe" to value that makes sense, and be sure to use your
editors [Rename] option, or update all values to match.
Just because the Singleton itself is threadsafe does not mean that all methods that might be contained are automatically threadsafe.
If threading is important, use threadsafe variables, such as:
System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue>
https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentdictionary-2
rather than:
System.Collections.Generic.Dictionary<TKey,TValue>
https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2
Alternatively, lock() can be used in a pinch, but there is the potential for slight performance hits.
Any field, property, or method not marked with "// REQUIRED" means that it's just a sample and can be removed or changed as needed.
Comments are inline as a reminder and as a point of education for those not familiar with Singletons.
Initial snippet added 12/08/2018 - JSW (Xepherys).
*/
public class SingletonLazyThreadsafe
{
#region Fields
// Private
private static readonly Lazy<SingletonLazyThreadsafe> lazy = new Lazy<SingletonLazyThreadsafe>(() => new SingletonLazyThreadsafe()); // REQUIRED
private int changeCount;
private int myInteger;
private string myString;
// Public
public char MyPublicChar; // Note: Even though it's a field, if it's publicly accessible, I generally capitalize the first letter. This is a personal design choice. Most folk tend to use lowercase for fields regardless of their accessibility level.
#endregion
#region Properties
// Note: Private getter/setter for private field.
private int ChangeCount
{
get
{
return this.changeCount;
}
set
{
this.changeCount = value;
}
}
// Note: Public getter/setter for private field.
public int MyInteger
{
get
{
return this.myInteger;
}
set
{
this.myInteger = value;
}
}
// Note: Public getter / protected setter for private field. This allows a {get} from anywhere, but only a {set} from inside the class or derived classes.
public string MyString
{
get
{
return this.myString;
}
protected set
{
this.myString = value;
}
}
#endregion
#region Constructors
private SingletonLazyThreadsafe() // REQUIRED
{ }
public static SingletonLazyThreadsafe Instance // REQUIRED
{
get
{
return lazy.Value;
}
}
#endregion
#region Methods
// Note: This is a public method that just changes the myInteger field. It's useless since the property is public, but it's just an example. It also call IncreaseCount().
public void IncrementInteger(int value)
{
this.MyInteger = value;
IncreaseCount();
}
// Note: This is a public method that just changes the myString field. It's useless since the property is public, but it's just an example. It also call IncreaseCount().
public void ChangeString(string value)
{
this.MyString = value;
IncreaseCount();
}
// Note: This is a private method, which means it can only be called by other methods in this class, and not publicly or outside of the class. While it could directly change
// 'changeCount', I also have it making changes via the private 'ChangeCount' property, which is also only accessible inside the class.
private void IncreaseCount()
{
this.ChangeCount++;
}
#endregion
}
}

Unity: GetComponent<BaseClass<T>> - are there any workarounds for this?

If an object has a component with a baseclass BaseClass<T>, calling GetComponent<BaseClass<T>>() will not return that component. The generic argument seems to throw it off, as a BaseClass without using generics will correctly return the derived class as a component when GetComponent<BaseClass>() is called.
Does anyone know a solid workaround for this? The use of a generic arg in this class is somewhat important, so I'd obviously rather not re-write the program's class structure just to accommodate this.
Here's a rough sketch of the classes in question
//the base class that I'd like to be able to fetch the subclasses of using GetComponent
public abstract class BaseUIClass<T> : MonoBehaviour where T :BaseEntity {}
//EntityType1&2 are derived from BaseEntity
public class DerivedUIClass1 : BaseUIClass<EntityType1> {}
public class DerivedUIClass2 : BaseUIClass<EntityType2> {}
BaseUIClass has this method:
public virtual void Setup(T entity) {}
Which needs to be called shortly after the component is added to a GO.
EDIT:
Effectively what I'm looking to do is the following, without having to hard-code in (I want to actually make use of the generic args I've defined)
if(uiClassObj is typeof(DerivedUIClass1) go.GetComponent<BaseUIClass<EntityType1>>();
else if(uiClassObj is typeof(DerivedUIClass2) go.GetComponent<BaseUIClass<EntityType2>>();
//etc
But considering that there is a component of type BaseUIClass<BaseEntity> on the go, and the two+ derived classes I'm interested in are defined by DerivedUIClass1<EntityType1> and DerivedUIClass2<EntityType2>, the conversion should surely just be implicit?
You can't do what you want the way you want, because Unity doesn't accept components which are generic classes.
I.E., if you have:
public class MyGenericClass<T> : MonoBehaviour {}
you will not be able to add it as a component unless you specify T via a subclass inheriting from it:
public class MySpecifiedClass : MyGenericClass<[specificType]> {}
So, to solve your problem, you should simply implement a specific interface for everything that should be done when the base class is added as a component. I'll show you an example with float and int derived types, you can extend easily to any type you need.
BaseClass
using UnityEngine;
public interface ISetup {
void CallSetup();
}
public class BaseClass<T> : MonoBehaviour, ISetup {
public T myEntity;
public void CallSetup() {
Setup(myEntity);
}
private void Setup(T entity) {
Debug.Log(entity);
//Your setup code
}
}
Your components classes
public class BaseClassInt : BaseClass<int> {
private void Awake() {
myEntity = 25;
}
}
public class BaseClassFloat : BaseClass<float> {
private void Awake() {
myEntity = 10.6f;
}
}
Code that gets the interface and calls Setup()
var componentsWithSetup = GetComponents<ISetup>();
foreach (var component in componentsWithSetup) {
component.CallSetup();
}
One workaround would be to use a specific type instead of a generic type at the top level for each type that you need the base class for.
For example:
public class SpecificToFirstTypeClass : BaseClass<FirstType>
{
}
and then use GetComponent<SpecificToFirstTypeClass>
Based on a suggestion from this answers.unity.com question
I couldn't believe this didn't work so I hacked it using tags, where UI is a base, abstract class:
public UI currentUI;
public void GetUI()
{
foreach (Transform child in transform)
{
if (child.tag == "UI Canvas")
{
currentUI = child.GetComponent<UI>();
}
}
}
Where I may have a different active "UI" depending on the scene. It might be the main game scene, or the menu scene. Now, I can just interact with the UI manager via generic/abstract methods like LoadUI() or HideUI().
Tbf, this really should be handled by events but it's overkill for my current project.

How do I combine a Controlled Lifetime relationship type (i.e. Owned<T>) with a delegate factory?

In my application, I have a service that requires a constructor parameter not resolved by Autofac, that I instantiate using a delegate factory:
public class Service
{
public Service(string parameter /*, ... other dependencies */)
{
}
public delegate Service Factory(string parameter);
}
This works great! I really love this feature.
I also like the Controlled Lifetime relationship, so I can let my component depend on a Func<Owned<ISomething>> like this:
public class Component
{
private Func<Owned<ISomething>> _somethingFactory;
/* constructor omitted for brevity */
public void DoSomethingUseful()
{
using (var ownedSomething = _somethingFactory())
{
/* Lots of useful code here */
}
}
}
My problem is that now I want to combine the two. I can't have an instance of Func<Owned<Service>> injected, because it needs that parameter, so my current solution is to abstract the factory away into another service, say IServiceFactory:
public interface IServiceFactory
{
Service Create(string parameter);
}
...implemented as such:
public class ServiceFactory : IServiceFactory
{
private Service.Factory _internalFactory;
public ServiceFactory(Service.Factory internalFactory)
{
_internalFactory = internalFactory;
}
public Service Create(string parameter)
{
return _internalFactory(parameter);
}
}
My component then becomes this:
public class Component
{
Func<Owned<IServiceFactory>> _serviceFactoryFactory;
/* ... */
}
The need for such a field name leaves a bad taste in my mouth to the point that I suspect there must be a cleaner way to handle this case.
Is there another way?
You could change your injected factory to include the string parameter:
private Func<string, Owned<ISomething>> _somethingFactory;
Then you can pass the string to the factory when you want to create a new instance:
public void DoSomethingUseful()
{
using (var ownedSomething = _somethingFactory("my parameter"))
{
/* Lots of useful code here */
}
}
I've created a .NET Fiddle with a small working sample.

Does ICommand always requires an object as a parameter?

When I implement the ICommand interface, the following methods are created
#region ICommand Members
public bool CanExecute(object parameter)
{
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
}
#endregion
The interesting part is
public void Execute(object parameter)
{
}
Simply because it indicates that it expects 1 parameter. What if I don't need to pass a parameter? In my ViewModel I have the following code
public class DownloadViewModel : BaseViewModel
{
public ICommand BrowseForFile { get; set; }
public string File { get; set; }
public DownloadViewModel()
{
BrowseForFile = new RelayCommand(new Action<object>(OpenDialog));
}
private void OpenDialog(object o)
{
var dialog = new System.Windows.Forms.FolderBrowserDialog();
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
File = dialog.SelectedPath;
}
}
The OpenDialog method does not require the parameter but it appears as if I have to just so I can satisfy the Interface.
Am I doing this right or have I missed the point?
Yes, ICommand always needs an object and RelayCommand too. If you don't need it, you pass null and don't use it in your method, which is ugly.
I would use Prism's DelegateCommand instead. This exists in a non-generic version, which doesn't take parameters:
Command = new DelegateCommand(DoSomething);
CommandWithParameter = new DelegateCommand<int>(DoSOmethingWithInt);
Its in the PRISM assembly, which you have to download and reference.
using Microsoft.Practices.Prism;
PRISM
Alternatively, use the MVVMLight toolkit, which provides a command class which does basically the same thing. There is no point in using MVVM without a MVVM framework anyway. I can recommend PRISM, also for it's basic stuff like the DelegateCommand or the EventAggregator.
The fact that Execute takes a parameter is irrelevant to the method from your ViewModel. The only thing that affects what parameters OpenDialog needs is your implementation of ICommand.
If your implementation is, for example:
public class MyRandomCommand : ICommand
{
private readonly Action _action;
public MyRandomCommand(Action action)
{
_action = action;
}
public void Execute(object parameter)
{
_action();
}
...
}
Then no parameters will be required for your OpenDialog method, as you can create a command as follows:
public ICommand Command { get { return new MyRandomCommand(OpenDialog); } }
You can, however, require any signature you like for the method you are passing to your command.
The most common, off-the-shelf implementations of RelayCommand can take methods with either 0 or 1 parameter and will be called from Execute appropriately.

AOP using Windsor and bulk registering classes

I am trying to configure an application such that types from assemblyA can be used by my console to allow for logging in an AOP style. The JournalInterceptor will just write out method calls, input and maybe output arguments to a log file or datastore of some kind.
I can register one type at a time but I would like to register all types in one go. Once I get going I may add some filtering to the registered types but I am missing something.
I am trying to use Classes.FromAssemblyContaining but am not sure how to get at an IRegistration instance for the call to WindsorContainer::Register
Any clues?
// otherAssembly.cs
namespace assemblyA
{
public class Foo1 { public virtual void What(){} }
public class Foo2 { public virtual void Where(){} }
}
// program.cs
namespace console
{
using assemblyA;
public class JournalInterceptor : IInterceptor {}
public class Program
{
public static void Main()
{
var container = new Castle.Windsor.WindsorContainer()
.Register(
Component.For<JournalInterceptor>().LifeStyle.Transient,
// works but can't be the best way
Component.For<Foo1>().LifeStyle.Transient
.Interceptors<JournalInterceptor>(),
Component.For<Foo2>().LifeStyle.Transient,
.Interceptors<JournalInterceptor>(),
// how do I do it this way
Classes.FromAssemblyContaining<Foo1>()
.Pick()
.LifestyleTransient()
.Interceptors<JournalInterceptor>()
);
Foo1 foo = container.Resolve<Foo1>();
}
}
}
Implement a Pointcut. In Castle Windsor this is done by implementing the IModelInterceptorsSelector interface.
It would go something like this:
public class JournalPointcut : IModelInterceptorsSelector
{
public bool HasInterceptors(ComponentModel model)
{
return true; // intercept everything - probably not a good idea, though
}
public InterceptorReference[] SelectInterceptors(
ComponentModel model, InterceptorReference[] interceptors)
{
return new[]
{
InterceptorReference.ForType<JournalInterceptor>()
}.Concat(interceptors).ToArray();
}
}
Then register the Interceptor and the Pointcut with the container:
this.container.Register(Component.For<JounalInterceptor>());
this.container.Kernel.ProxyFactory.AddInterceptorSelector(new JournalPointcut());
For in-depth explanation, you may want to see this recording.