mvvmcross ViewModel's init() is called at last - ios

I have a DetailViewModel which has several custom buttons and initialize them in Init().
public class DetailViewModel{
...
public async void Init(DetailParameter params){
...
CustomButtons.Add(new CustomButton(this, "1")); //3
CustomButtons.Add(new CustomButton(this, "2"));
...
}
}
Then in the detail view, I have several buttons and bind them with custom buttons in DetailViewModel.
public partial class DetailView{
private List<CustomButton> m_customButtons;
public List<CustomButton> CutomButtons{
get { return m_customButtons; }
set { m_customButtons = value; //2
foreach(CustomButton button in m_customButtons){
UIButton myButton = new UIButton ();
Add(myButton);
}
}
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var set = this.CreateBindingSet<DetailView, DetailViewModel>();
set.Bind (this).For (v=>v.CustomButtons).To (vm=>vm.CustomButtons);//1
set.Apply ();
}
}
The problem is that ViewModel's Init() is called at last.
So always m_customButtons has set by 0 count, then ViewModel's Init() is called.
I know about CIRS, but how can solve this?

There's plenty you could do to change your binding to make it work in this async scenario - including using observable collections.
However, the simplest route in your current setup might just be to change the entire CustomButtons list in your ViewModel instead - e.g. something like:
var customButtons = new List<CustomButton>() {
new CustomButton(this, "1"),
new CustomButton(this, "2")
};
CustomButtons = customButtons;
RaisePropertyChanged(() => CustomButtons);
In this "one-off" scenario, this implementation should work for you. For more advanced dynamic scenarios, it might be worthwhile looking at INotifyCollectionChanged implementations too.

Related

Difference in static and class method in dart

I am little new to dart. I am trying to understand the difference between these two methods. Are both methods different or same? Where should I use one above another? Can someone explain it to me?
class A {
A.executor1() {
print('executor one is called');
}
static executor2() {
print('executor two is called');
}
}
Meanwhile neither of the method call is required to make a new instance? both are called using the class name.
void main() {
A.executor1(); // Will print "executor one is called"
A.executor2(); // Will print "executor two is called"
}
A.executor1() is a named constructor. static executor2() is a static method.
With an IDE (or dartpad.dev) you can see the different return types when you are placing the cursor over each method:
void main() {
A.executor1(); // (new) A A.executor1()
A.executor2(); // dynamic executor2()
}
static methods can be called without creating an instance of the class. executor1 will have access to this and so on because it's attached to an actual instance, but static methods will not because they aren't attached to anything.
Consider (in Javascript):
class Bicycle {
static numWheels = 2;
constructor(color) {
this.color = color;
}
static numberOfWheels() {
console.log(`Every bike has ${this.numWheels} wheels.`);
}
myColor() {
console.log(`This bike is ${this.color}.`);
}
}
// property of an instance
new Bicycle('red').myColor();
// available for anyone!
Bicycle.numberOfWheels();

Hide UIView on view load - Xamarin iOS and MvvmCross

I'm trying to hide an ui element on view load. I'm using Xamarin iOS and MvvmCross (6.2.3.0). In my view, I create an uitextfield and add following binding:
public override void ViewDidLoad()
{
//adding uitextfield
var set - this.CreateBindingSet(MyViewConroller, MyViewModel>();
set.Bind(uitextfield).For("Visibility").To(vm => vm.FieldVisibility).TwoWay().WithConversion("Visibility");
}
And here is my viewmodel:
public MyViewModel : MvxViewModel
{
private bool _fieldVisibility;
public bool FieldVisibility
{
get {return _fieldVisibility;}
set {
SetProperty(ref _fieldVisibility, value);
}
public override Task Initialize() {
FieldVisibility = false;
}
But when the view is loaded, my uitextfield is still visible. I tried to call RaisePropertyChanged, but it didn't help:
private bool _fieldVisibility;
public bool FieldVisibility
{
get {return _fieldVisibility;}
set {
SetProperty(ref _fieldVisibility, value);
RaisePropertyChanged(nameof(FieldVisibility));
}
It works, when I change some other viewmodel property and simply call:
private string _otherProperty;
public string OtherProperty
{
get {return _otherProperty;}
set {
SetProperty(ref _otherProperty, value);
FieldVisibility = false;
RaisePropertyChanged(nameof(FieldVisibility));
}
but I'd like to have this uitextfield hidden on view load. Can you suggest any solution for that? I'd be very grateful for any hint. Thanks!!
We have strongly typed bindings nowadays for stuff like this:
set.Bind(uitextfield).For(v => v.BindVisible()).To(vm => vm.FieldVisibility);
You don't really need the visibility converter here, should work without it.
Remember to also call Apply() on your binding set.
Also TwoWay() won't do anything here, because there are no Binding Targets which allow for Two Way bindings for UIView visibility.

Why in StructureMap are Singleton classes disposed of and transients aren't

In my application I've noticed that if I mark a class in the SM registry as a Singleton type it gets disposed of, however if don't specify any Singleton it doesn't get disposed of.
What and why are the reasons for this?
public class IoC
{
public static IContainer Init()
{
var container = new Container(x =>
{
x.Scan(s => {
s.TheCallingAssembly();
s.AssembliesFromApplicationBaseDirectory();
s.WithDefaultConventions();
});
// disposed is called on this class but not if .Singleton() is removed
x.For<IMyService>().Singleton();
});
return container;
}
}
class Program
{
static void Main(string[] args)
{
using (var container = IoC.Init())
{
var theStory1 = container.GetInstance<MyService>();
theStory1.TheMethod();
}
}
}
Singleton lifecycle is bound to the container's scope thus when disposing the container it takes care to dispose all singletons implementing IDisposable. With transients and other lifecycles like HttpContextScoped it is up to developer to dispose them manually when no longer need them.
Transient disposables are tricky a little bit in terms of how it should be handled. Imagine case like this one below:
public class ClassWithDisposableTypeDependency
{
private readonly ISampleDisposable disposableType;
public ClassWithDisposableTypeDependency(ISampleDisposable disposableType)
{
this.disposableType = disposableType;
}
public void SomeAction()
{
using (this.disposableType)
{
this.disposableType.DoSomething();
}
}
}
What will happend when SomAction() won't be executed? Dispose won't be called on disposableType field. In fact in this case ClassWithDisposableTypeDependency should also implement IDisposable and dispose its disposable dependencies.
But there is a better way to handle such cases. In mentioned case the main issue is to defer creation of a dependency to a moment when we really need that objects. We can achieve that in many ways: func, lazy, factory, etc. Here is possible solution with usage of func.
public class ClassWithDisposableTypeFuncDependency
{
private readonly Func<ISampleDisposable> disposableTypeFactory;
public ClassWithDisposableTypeFuncDependency(Func<ISampleDisposable> disposableTypeFactory)
{
this.disposableTypeFactory = disposableTypeFactory;
}
public void SomeAction()
{
var disposable = this.disposableTypeFactory();
using (disposable)
{
disposable.DoSomething();
}
}
}
This is how we need to setup it in StructureMap:
var container = new Container(c => c.For<ISampleDisposable>().Use<SampleDisposable>());
var clazz = container.GetInstance<ClassWithDisposableTypeFuncDependency>();
clazz.SomeAction(); // dependency is created and disposed
Hope this helps!

MvvmCross: Binding a BaseView Property to a BaseViewModel Property

What I am trying to achieve here is a global loading indicator with MvvmCross.
From what I gathered so far it appears that I can implement this by using a BaseView and BaseViewModel. The BaseViewModel should contain an IsLoading property that the BaseView can Bind to. Therefore, I can set IsLoading to true in any of my ViewModels to cause the indicator to be displayed.
The BaseViewModel looks like this:
public abstract class BaseViewModel : MvxViewModel
{
private bool _isLoading = false;
public bool IsLoading
{
get { return _isLoading; }
set { _isLoading = value; RaisePropertyChanged(() => IsLoading); }
}
private string _loadingMessage = "Loading...";
public string LoadingMessage
{
get { return _loadingMessage; }
set { _loadingMessage = value; RaisePropertyChanged(() => LoadingMessage); }
}
}
As for binding to the ViewModel, this issue was addressed here: https://stackoverflow.com/a/10930788
I was successfully able to listen to IsLoading by attaching to the PropertyChanged event, however, since this is not a "real" binding it will not fire if IsLoading is set to true before you attach to the event (Such as before the view is loaded).
Next I attempted to call AddBindings to attach to my BaseViewModel in order to create a real binding between the two properties, although this does not appear to work (no errors).
Here is what my BaseView currently looks like for iOS:
public abstract class BaseView<TViewModel> : MvxViewController where TViewModel : BaseViewModel
{
public TViewModel ViewModel
{
get { return (TViewModel)base.ViewModel; }
set { base.ViewModel = value; }
}
protected BaseView(string nib, NSBundle bundle) : base(nib, bundle)
{
}
private LoadingOverlay _loadingOverlay;
public override void ViewDidLoad()
{
base.ViewDidLoad();
_loadingOverlay = new LoadingOverlay(View.Frame);
this.AddBindings(new Dictionary<object, string>()
{
{this, "{'IsLoading':{'Path':'IsLoading'}}"},
{_loadingOverlay, "{'LoadingMessage':{'Path':'LoadingMessage'}}"}
});
}
public bool IsLoading
{
set
{
if (value)
View.Add(_loadingOverlay);
else
_loadingOverlay.Hide();
}
}
}
Are there any pitfalls to AddBindings that I may be unaware of? or is there a newer method altogether that I should be using?
I Appreciate the help, Thanks.
If you are using v3, then by default you must change over to the new 'Swiss' style bindings.
These change Json text like:
"{'LoadingMessage':{'Path':'LoadingMessage'}}"
Into simpler text like:
"LoadingMessage LoadingMessage"
For more on this, see http://blog.ostebaronen.dk/2013/01/awesome-mvvmcross-swiss-bindings-for.html
One further option you can use in v3 is 'fluent bindings'. To see these in action, see all the iOS samples in the N+1 series - http://mvvmcross.wordpress.com/, or questions like Fluent Bindings and UIButton titles
Eg something like:
this.CreateBinding().For("LoadingMessage").To("LoadingMessage").Apply();
It may also help for debugging if you enable additional trace - see MvvmCross Mvx.Trace usage

autofac "Hello World" app in C# - initialization

I am looking for some help with a simple "Hello World" example of DI. What I don't understand is how to initialize the classes "Foo" and "Bar" within a DI framework (autofac).
namespace AutofacTesting
{
//these classes are intended to be used with autofac / DI
public interface IFooBar
{
void Draw();
}
public class Bar : IFooBar
{
public void Draw()
{
MessageBox.Show("Drawing something in Bar");
}
}
public class Foo : IFooBar
{
public void Draw()
{
MessageBox.Show("Drawing somthing in Foo");
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var builder = new ContainerBuilder();
builder.RegisterType<Bar>().As<IFooBar>();
builder.RegisterType<Foo>().As<IFooBar>();
var container = builder.Build();
var taskController = container.Resolve<IFooBar>();
taskController.Draw();
int a = 1;
}
}
}
I think you mean you want to resolve a Bar or Foo class as the concrete implementation, not instantiate it. If so you could write:
var builder = new ContainerBuilder();
builder.RegisterType<Bar>().Named<IFooBar>("Bar");
builder.RegisterType<Foo>().Named<IFooBar>("Foo");
var container = builder.Build();
var taskController = container.ResolveNamed<IFooBar>("Bar");
taskController.Draw();
I also realize this is a hello world application, but be careful not to fail into the anti-pattern of using a service locator (i.e. using contain.Resolve all over the place). Instead, consider designs which will allow you to have all the registration and resolving happen in the same place, named a composition root.
I mention this caution becuase having this level of ambiguity (i.e. multiple concreate types being registered for a given interface) can cause one to start using the service locator pattern. Instead, in more complex applications, consider refactoring your API to have less ambiguity upon resolving registered types.

Resources