FreshMvvm
FreshMvvm copied to clipboard
multiple parameters for init method
Is it possible to have multiple parameters for init method when I need to pass more than 1. Of course I can create custom object with those parameters as property but this is kind of cumbersome. thanks :)
I don't think a change is needed here.
It is not difficult to pass in params with object[].
This is much faster than creating an object with custom properties.
Here's an example I just finished testing locally.
In the ICommand:
public ICommand AddContactCommand
{
get {
return new Command(async () => {
// Initialize the array with three different classes.
object[] threeBodyProblem = new object[] { _repository, Contacts[0], "string" };
await CoreMethods.PushPageModel<ContactPageModel>(threeBodyProblem);
});
}
}
In the ContactPageModel's Init method:
public override void Init(object initData)
{
var result = initData as object[];
var indexZero = result[0] as Repository;
var indexOne = result[1] as Contact;
var indexTwo = result[2] as string;
}
I recommend offering this as a solution and not modifying the methods. Don't forget those null checks in real code =)
Another alternative, that also might be nicer to use when C# 7 comes out (with the new Tuple deconstruction feature etc.).
CoreMethods.PushPageModel<SomeModel>(Tuple.Create(1, "a"));
public override void Init(object initData)
{
var parameters = (Tuple<int, string>)initData;
}
Another way of getting multiple parameters, is to add a Init(params object[] parameters), and then you will have two Init methods. But I think the answer to @C0D3Name is better.
There is also another alternative that might work.
If the PushPageModel can take a Action<TViewModel>
, then it should be possible to do something like:
CoreMethods.PushPageModel<SomeModel>((vm) => vm.Init("a", 1));
public override void Init(string a, int b) //Can however be called whatever you want.
{
//
}
This should then be strongly typed and everything, as it don't depend on any baseclass.
@oddbear tuple is a good way of resolving this issue but requires c#7. @C0D3Name I dont think this is a good solution. because in some cases I might need to pass over different types. I handle it as below. In this case your using Object will fail. many people dont like to work with Object type I believe.
if (initData is Customer) { }
@EmilAlipiev It is possible to cast to another type from an object. This satisfies the test within your if statement. I have written a simple, 1-file console application to prove this point, it utilizes similar logic to your example if statement. Attached is the output from running the application.
`using System;
namespace ConsoleApplication1 {
public class Class1 {
public string ClassName { get { return "Class1"; } }
}
public class Class2 {
public string ClassName { get { return "Class2"; } }
}
class Program {
static void Main(string[] args) {
ClassTester(new Class1());
ClassTester(new Class2());
ClassTester(new object());
Console.ReadKey();
}
private static void ClassTester(object theParameter) {
if(theParameter as Class1 != null) {
var classCast = theParameter as Class1;
Console.WriteLine(classCast.ClassName);
}
else if(theParameter as Class2 != null) {
var classCast = theParameter as Class2;
Console.WriteLine(classCast.ClassName);
}
else {
Console.WriteLine("Could not cast object to a known type.");
}
}
}
}`
Sorry about replying an old issue, but I do have a similar issue.
I wonder, is it possible to fetch some values from the previous PageModel? Or maybe I could just send the current instance of the PageModel to the next page, so I don't have to pack everything in an object and unpack in the new PageModel class. Any suggestion?
Sounds like this would not scale easily.
One navigation to the page would probarbly work fine, but when you can access a page from 3-4 others (or 100)... then I would guess this to be really hard to maintain.
I am thinking the code inside the Init from just 4 diffrent previous pages would be something like:
switch(model)
{
case model is AViewModel: /* DoSomething */ break;
case model is BViewModel: /* DoSomething */ break;
case model is CViewModel: /* DoSomething */ break;
case model is DViewModel: /* DoSomething */ break;
}
However, the previous viewModel can have a common interface (or similar), to reuse the "fetch logic".
Sounds like this would not scale easily.
Thanks for your reply. Or maybe send an instance of NextPageModel could be an alternative way. But by doing this, it actually moves the "init" stuff to a constructor. Is this feasible or is there any violation against the design of fresh MVVM? Cheers.