[英]Xamarin.Forms and Prism - How to pass data and navigate to another view?
這是我在這里的第一個問題,大家好。 我正在使用 Prism 開發 Xamarin.Forms 中的移動應用程序。 我創建了 ListView,其中顯示了數據庫中的數據。
當用戶在所選行中單擊時,應用程序應導航到新視圖並從 ListView 傳遞所選項目。
<ListView x:Name="DefectsBase"
RowHeight="65"
ItemsSource="{Binding Defects}"
ItemSelected="ShowDetailsEvent"
IsPullToRefreshEnabled="true"
RefreshCommand="{Binding Refresh}"
IsRefreshing="{Binding IsRefreshing}">
代碼后端:
async void ShowDetailsEvent(object sender, EventArgs e)
{
var myListView = (ListView)sender;
var myItem = myListView.SelectedItem;
var p = new NavigationParameters();
p.Add("selectedDefect", myItem);
await _navigationService.NavigateAsync("DefectDetailsView", p);
}
不幸的是,應用程序沒有響應在 ListView 中按下選定的行。
正如我所看到的,您已經在使用Prism
,並且您有一個包含項目的列表頁面,並且您希望根據用戶在 ListView 中點擊的選定/錄制/選擇的項目導航到一些詳細信息頁面。
我們的想法是將盡可能多的代碼和邏輯移動到視圖 model 並保留我們的代碼隱藏。 使用Prism
和EventToCommand
行為很容易解決這個問題。
在下面的示例和答案中,我將向您展示如何用幾行代碼和一種很好的代碼方法來解決這個問題。
首先,我建議您使用EventToCommand
行為,您可以將其包含在 prism xmlns 中,如下所示: xmlns:prism="http://prismlibrary.com"
,稍后您可以將其與 ListView 一起使用。
從 ListView 中刪除 ItemSelected 事件並將有關它的標記移動到<ListView.Behaviors>
部分。 這是我綁定到汽車模型的一些ObserverableCollection
的ListView
的代碼示例:
<ListView ItemsSource="{Binding Cars}">
<ListView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Behaviors>
<prism:EventToCommandBehavior EventName="ItemTapped"
Command="{Binding SelectedCarCommand}"
EventArgsParameterPath="Item" />
</ListView.Behaviors>
這里的主要部分是<ListView.Behaviors>
,您可以在其中看到我綁定到 SelectedCarCommand ,當用戶點擊列表中的某些項目時將調用該命令。 我為此使用ItemTapped
事件,並將列表中當前的“錄音”項目作為參數傳遞。
為了在此頁面的 model 中遵循此 XAML 部分,我聲明了DelegateCommand
和調用命令時將調用的方法。 視圖 model 部分如下所示:
這是我的 CarListPageViewModel,看看 DelegateCommand 和 SelectedCar 方法。
public class CarListPageViewModel
{
private readonly INavigationService _navigationService;
public ObservableCollection<Car> Cars { get; set; }
public DelegateCommand<Car> SelectedCarCommand { get; private set; }
public CarListPageViewModel(INavigationService navigationService, IDataProvider dataProvider)
{
_navigationService = navigationService;
// Insert test data into collection of Cars
Cars = new ObservableCollection<Car>(dataProvider.GetData());
SelectedCarCommand = new DelegateCommand<Car>(SelectedCar);
}
private async void SelectedCar(Car selectedCar)
{
NavigationParameters navigationParameters = new NavigationParameters
{
{ "selectedCar", selectedCar }
};
await _navigationService.NavigateAsync(nameof(CarDetailsPage), navigationParameters);
}
}
正如你所看到的,我們定義了DelegateCommand
,參數的類型將被傳遞,在我的例子中,這是 Car class,與 ListView 中的項目相同的 class。
在構造函數中,我進行了初始化並定義了將要調用的方法,該方法有一個 Car 類型的參數。
當用戶點擊 ListView 中的一個項目時,將調用 SelectedCar(方法),我們可以使用NavigationParameters
和NavigationService
將數據傳遞給下一個視圖。
為了檢索傳遞的數據,我們可以在詳細視圖 model 中使用INavigationAware
並使用OnNavigatedTo
方法訪問正在傳遞的數據。
這是我的 CarDetailsPageViewModel,看看OnNavigatedTo
方法。
public class CarDetailsPageViewModel : BindableBase, INavigationAware
{
private string carTitle;
public string CarTitle
{
get { return carTitle; }
set { SetProperty(ref carTitle, value); }
}
private string photoUrl;
public string PhotoUrl
{
get { return photoUrl; }
set { SetProperty(ref photoUrl, value); }
}
public CarDetailsPageViewModel() { }
public void OnNavigatedTo(INavigationParameters parameters)
{
if (parameters.ContainsKey("selectedCar"))
{
Car car = parameters.GetValue<Car>("selectedCar");
if (car != null)
{
CarTitle = $"{car.Make} {car.Model}";
PhotoUrl = car.PhotoUrl;
}
}
}
public void OnNavigatedFrom(INavigationParameters parameters) { }
}
從這個答案和示例中,您可以看到:
EventToCommand
行為與ListView
一起使用DelegateCommand
您可以在我的 GitHub 配置文件中找到代碼和此示例。
希望這個答案對你有幫助!
祝你編碼好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.