jaspal singh khokhar
jaspal singh khokhar

Reputation: 11

c# xxx is a variable but is used like a type

i have a model in my xamarin forms app that is used to generate a dynamic navigation menu

 public class NavigationMenuItem
 {
        public string MenuText { get; set; }
        public string MenuIcon { get; set; }
        public Type TargetType { get; set; }
 }

 NavigationMenuItems.Add(new NavigationMenuItem
 {
        MenuText = "Settings",
        MenuIcon = "settings.png"
        TargetType = typeof(SettingsViewModel)
 });

i have some code that allows me to navigate to a page via the page's view model so that a view model never references a page directly but via its view model. this works when i hard code the view model :

await _navigator.PushAsync<PageViewModel>();

but if i try

 var vm = selectedItem.TargetType;
 await _navigator.PushAsync<vm>();

i get an error "vm is a variable but is used like a type"

how can i pass the type held in TargetType into PushAsync

thanks in advance

jas

Upvotes: 1

Views: 1438

Answers (2)

Ren&#233; Vogt
Ren&#233; Vogt

Reputation: 43946

You can't pass an instance of Type as a generic type argument to that method. But you could use reflection to achieve that:

var vm = selectedItem.TargetType;

MethodInfo mi = _navigator.GetType().GetMethod("PushAsync`1");
MethodInfo genericMethod = mi.MakeGenericMethod(vm);
await (Task)genericMethod.Invoke(_navigator);

So you retrieve the MethodInfo for the generic method definition and create a specific MethodInfo by providing the type to MakeGenericMethod.
Finally you can invoke that method and cast the returned object into a Task that you can await.

Upvotes: 0

ChrisF
ChrisF

Reputation: 137188

PushAsync is expecting a type at compile time to tell it which method it needs to call.

If you don't know until runtime then you either need to pass the view model as an argument:

await _navigator.PushAsync(vm);

or implement the navigation on the view model:

await vm.PushAsync();

Upvotes: 1

Related Questions