NavigateTo<T>()
函数位于App.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);
}
ItemListViewModel.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; }
DataCaptureViewModel.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; }
}
BaseViewModel.cs
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()
{
}
}
}
我一直在使用 MVVM 模式开发 Xamarin.Forms 应用程序并调用 App.NavigateTo<T>()
当需要导航到另一个页面时。现在我想通过 ObservableCollection<Item>
进入我正在导航到的页面。我一直无法弄清楚如何使用NavigateTo<T>()
来做到这一点方法。我在 WPF
中询问过和C#
聊了很多圈子,但还没有找到解决方案。有什么想法吗?
如果需要显示更多代码,请告诉我。
最佳答案
选项-1。使用附加属性
工作原理:为了传递一些导航参数 - 您可以使用附加属性存储 View (和 View 模型)的状态。我们将绑定(bind)模式保留为“OneWayToSource” - 这样一旦绑定(bind) - 它只会更新 ViewModel,而不是 View 本身的附加属性;
这样,一旦 NavigateTo
方法显式设置附加属性的值,我们就可以在 View 上设置绑定(bind);一旦将 viewmodel 分配给 View 的 BindingContext
- viewmodel 就会因绑定(bind)而使用附加值进行更新。
步骤:
创建附加的可绑定(bind)属性。
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
以接受参数并分配属性值。
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);
}
确保在 (DataCapture) View XAML 中创建与属性的绑定(bind)。例如:
<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>
或者,选项 2。在 BaseViewModel
中使用虚拟方法
重构 NavigateTo
以接受参数并更新 View 模型。
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
,或者在BaseViewModel
中创建一个类似SetNavigationContext
的方法
public abstract class BaseViewModel : INotifyPropertyChanged
{
.....
public virtual void SetNavigationContext(object context)
{
}
在DataCaptureViewModel
中重写此方法
public class DataCaptureViewModel : BaseViewModel
{
...
public ObservableCollection<Item> SelectedItems { get; set; }
public override void SetNavigationContext(object context)
{
var selectedItems = context as ObservableCollection<Item>;
SelectedItems = selectedItems;
}
}
关于c# - 使用静态 NavigateTo<T> 方法在 Xamarin.Forms 中导航时如何传递参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45765081/