在使用静态NavigateTo <t>方法在Xamarin.Forms中导航时,如何传递参数?

时间:2017-08-18 21:08:38

标签: c# mvvm xamarin.forms

位于App.cs中的

/** * @ManyToMany(targetEntity="Tags") * @OrderBy({"title" = "ASC"}) */ private $tags; 函数

NavigateTo<T>()

ItemListViewModel.cs

public static Task NavigateTo<T>()
    where T : BaseViewModel
{
    // do some very simple navigation/lookups
    // basically, just remove the "Model" part of the VM and that is the page
    // "converntion-based" :)
    var viewModelName = typeof(T).Name;
    var pageType = typeof(MainView);
    var pageNamespace = pageType.Namespace;
    var pageAssembly = pageType.GetTypeInfo().Assembly;
    var newPageName = viewModelName.Substring(0, viewModelName.Length - "Model".Length);
    var newPageType = pageAssembly.GetType($"{pageNamespace}.{newPageName}");

    var newPage = Activator.CreateInstance(newPageType) as Page;
    var currentPage = ((NavigationPage)Current.MainPage).CurrentPage;
    return currentPage.Navigation.PushAsync(newPage);
}

DataCaptureViewModel.cs

public ItemListViewModel()
{
    NextPageCommand = new Command(() => App.NavigateTo<DataCaptureViewModel>());
}

public ObservableCollection<Item> LocalItems
{
    get { return localItems; }
    set
    {
        localItems = value;
        Refresh(nameof(LocalItems));
    }
}

public Command NextPageCommand { get; private set; }

BaseViewModel.cs

public class DataCaptureViewModel : BaseViewModel
{
    public DataCaptureViewModel()
    {
        //will probably have to set passed in param to SelectedItems
        //once passing in params gets figured out
    }
    public ObservableCollection<Item> SelectedItems { get; set; }
}

我一直在使用MVVM模式开发Xamarin.Forms应用程序,并在需要导航到另一个页面时调用using System.ComponentModel; using System.Runtime.CompilerServices; namespace Application { public abstract class BaseViewModel : INotifyPropertyChanged { protected void Refresh([CallerMemberName]string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected bool Set<T>(ref T field, T value, [CallerMemberName]string propertyName = null) { if (!object.Equals(field, value)) { field = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); return true; } return false; } public event PropertyChangedEventHandler PropertyChanged; public virtual void OnDisappearing() { } public virtual void OnAppearing() { } } } 。我现在已经到了一个地步,我想将App.NavigateTo<T>()传递到我正在浏览的页面中。我无法使用ObservableCollection<Item>方法弄清楚如何执行此操作。我在NavigateTo<T>()WPF聊天圈中询问过但尚未找到解决方案。有什么想法吗?

如果需要显示更多代码,请告诉我。

1 个答案:

答案 0 :(得分:1)

选项-1。使用附加财产

工作原理 :为了传递一些导航参数,您可以使用附加属性存储视图(和视图模型)的状态。我们将绑定模式保持为&#39; OneWayToSource&#39; - 这样一旦绑定 - 它只更新ViewModel,而不是View本身的附加属性;

这样,一旦sudo方法显式设置附加属性的值,我们就在视图上设置绑定;只要将viewmodel分配给视图NavigateTo,viewmodel就会因绑定而使用附加值进行更新。

<强> 步骤

创建附加的可绑定属性。

BindingContext

重构public class NavigationContext { public static readonly BindableProperty ParamProperty = BindableProperty.CreateAttached("Param", typeof(object), typeof(NavigationContext), null, defaultBindingMode: BindingMode.OneWayToSource); public static object GetParam(BindableObject view) { return view.GetValue(ParamProperty); } public static void SetParam(BindableObject view, object value) { view.SetValue(ParamProperty, value); } // add more properties if more parameters to be passed.. } 以接受参数,并指定属性值。

NavigateTo

确保在(DataCapture)视图XAML中创建对属性的绑定。例如:

public static Task NavigateTo<T>(object param = null)
    where T : BaseViewModel
{
    // do some very simple navigation/lookups
    // basically, just remove the "Model" part of the VM and that is the page
    // "converntion-based" :)
    var viewModelName = typeof(T).Name;
    var pageType = typeof(MainView);
    var pageNamespace = pageType.Namespace;
    var pageAssembly = pageType.GetTypeInfo().Assembly;
    var newPageName = viewModelName.Substring(0, viewModelName.Length - "Model".Length);
    var newPageType = pageAssembly.GetType($"{pageNamespace}.{newPageName}");

    var newPage = Activator.CreateInstance(newPageType) as Page;
    if (param != null)
        NavigationContext.SetParam(newPage, param);

    var currentPage = ((NavigationPage)App.Current.MainPage).CurrentPage;
    return currentPage.Navigation.PushAsync(newPage);
}

或者,选项-2。在<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:SampleApp" x:Class="SampleApp.DataCaptureView" local:NavigationContext.Param="{Binding SelectedItems}"> <ContentPage.Content>

中使用虚方法

重构BaseViewModel以接受参数,并更新视图模型。

NavigateTo

重新使用public static Task NavigateTo<T>(object navigationContext = null) where T : BaseViewModel { // do some very simple navigation/lookups // basically, just remove the "Model" part of the VM and that is the page // "converntion-based" :) var viewModelName = typeof(T).Name; var pageType = typeof(MainView); var pageNamespace = pageType.Namespace; var pageAssembly = pageType.GetTypeInfo().Assembly; var newPageName = viewModelName.Substring(0, viewModelName.Length - "Model".Length); var newPageType = pageAssembly.GetType($"{pageNamespace}.{newPageName}"); var newPage = Activator.CreateInstance(newPageType) as Page; /* newPage.BindingContext ?? */ var viewModel = Activator.CreateInstance<T>(); if (param != null) viewModel.SetNavigationContext(navigationContext); newPage.BindingContext = viewModel; var currentPage = ((NavigationPage)Current.MainPage).CurrentPage; return currentPage.Navigation.PushAsync(newPage); } ,或在OnAppearing

中创建SetNavigationContext之类的方法
BaseViewModel

public abstract class BaseViewModel : INotifyPropertyChanged { ..... public virtual void SetNavigationContext(object context) { }

中覆盖此方法
DataCaptureViewModel