c# - 从另一个 NavPage 的 ListView 将 SelectedItem 绑定到根 NavPage UI 不起作用
问题描述
我想使用正确的导航栏按钮作为我的 ListView 的过滤器功能。我的第一种方法是下拉列表,但由于这在 iOS 中是不可能的,所以我尝试使用 NuGet 包绕过它Rg.Plugins.Popup
(我不想创建 CustomRenderer)。到目前为止,这一切都很好。
从我的其他 ListView 中选择后,我的 UI 没有更新。关于正确调试我的值更改。
这是我的视图模型:
public ProcessesPageViewModel()
{
Location = new Location { Name = "Default", Filter = "Default" };
AsyncCreateListLocations();
}
AsyncCreateListLocations() 只是一个任务:
void CreateListLocations()
{
downloadLocations = new DownloadLocations();
LocationList = downloadLocations.DownloadJSON().OrderBy(x => x.Name).ToList();
}
private Location _location;
public Location Location
{
get => _location;
set
{
SetValue(ref _location, value);
}
}
我的 XAML 来自根 ListView,过滤器应该稍后应用(尚未实现):
<ContentPage.ToolbarItems>
<ToolbarItem Text="{Binding Location.Name}" Clicked="Clicked_Location"/>
</ContentPage.ToolbarItems>
现在这是我的 PopUp 页面,其位置为 ListView:
<ListView x:Name="ProcessesListView"
ItemsSource="{Binding LocationList}"
SelectedItem="{Binding Location}"
WidthRequest="100"
HeightRequest="200"
ItemSelected="OnItemSelected"
VerticalOptions="Center">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Margin="5" FontAttributes="Bold" VerticalOptions="FillAndExpand" Grid.Row="0" Grid.ColumnSpan="2" Text="{Binding Name}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
async void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
{
await Navigation.PopPopupAsync();
}
使用 Acr.UserDialogs 编辑:
using Acr.UserDialogs;
using MyProject.Models;
using MyProject.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace MyProject.ViewModels
{
public class MyViewModel : BaseViewModel
{
private IUserDialogs userDialogs;
public MyViewModel(IUserDialogs userDialogs)
{
this.userDialogs = userDialogs;
}
DownloadProcesses downloadProcesses;
DownloadLocations downloadLocations;
public Command LoadItemsCommand { get; set; }
public Command ToolbarItemCommand { get; set; }
public MyViewModel()
{
Location = new Location { Name = "Default", Filter = "Default" };
LoadItemsCommand = new Command(ExecuteLoadItemsCommand);
ToolbarItemCommand = new Command(SetLocation);
AsyncCreateListProcesses();
AsyncCreateListLocations();
}
void CreateListProcesses()
{
downloadProcesses = new DownloadProcesses();
ProcessList = downloadProcesses.DownloadJSON().OrderByDescending(x => DateTime.Parse(x.Datum)).ThenByDescending(x => DateTime.Parse(x.Zeit)).ToList();
}
void CreateListLocations()
{
downloadLocations = new DownloadLocations();
LocationList = downloadLocations.DownloadJSON();
//LocationList = downloadLocations.DownloadJSON().OrderBy(x => x.Name).ToList();
}
async void SetLocation()
{
var selectedOptionDesc = await this.userDialogs.ActionSheetAsync("MyTitle", "MyCancelButtonText", null, null, this.LocationList.Select(l => l.Name).ToArray());
if (string.IsNullOrEmpty(selectedOptionDesc))
return;
var selectedOption = this.LocationList.FirstOrDefault(l => l.Name == selectedOptionDesc);
if (selectedOption == null)
return;
Xamarin.Forms.Device.BeginInvokeOnMainThread(() => this.Location = selectedOption);
}
public Task AsyncCreateListProcesses()
{
return Task.Run(() => CreateListProcesses());
}
public Task AsyncCreateListLocations()
{
return Task.Run(() => CreateListLocations());
}
async void ExecuteLoadItemsCommand()
{
if (IsBusy)
return;
IsBusy = true;
try
{
await AsyncCreateListProcesses();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
private List<Process> _processList;
public List<Process> ProcessList
{
get => _processList;
set => SetValue(ref _processList, value);
}
private List<Location> _locationList;
public List<Location> LocationList
{
get => _locationList;
set => SetValue(ref _locationList, value);
}
private Location _location;
public Location Location
{
get => _location;
set
{
if (value != null)
{
SetValue(ref _location, value);
}
}
}
}
}
解决方案
我建议您使用Acr.UserDialogs它真的很容易使用并且允许自定义。
为了执行您想要安装包的操作,请在您的 Android 项目的主要活动中对其进行初始化:
UserDialogs.Init(() => (Activity)Forms.Context)
将您的 IUserDialogs 注入您的ViewModel
:
private IUserDialogs userDialogs;
public MyViewModel(IUserDialogs userDialogs)
{
this.userDialogs = userDialogs;
}
并致电:
var selectedOptionDesc = await this.userDialogs.ActionSheetAsync("MyTitle", "MyCancelButtonText", null, null, this.LocationList.Select(l => l.Description).ToArray());
if (string.IsNullOrEmpty(selectedOptionDesc))
return;
var selectedOption = this.LocationList.FirstOrDefault(l => l.Description == selectedOptionDesc);
if (selectedOption == null)
return;
Xamarin.Forms.Device.BeginInvokeOnMainThread(() => this.Location = selectedOption);
如果您没有依赖注入引擎,那么您可以替换this.userDialogs.ActionSheetAsync(...)
为:
UserDialogs.Instance.ActionSheetAsync(...)
如果您仍然想使用您的库,可能它不会更新您的视图,因为您没有Location
在 MainThread 中设置属性,因此您必须将该 set 包装在 aXamarin.Forms.Device.BeginInvokeOnMainThread(() => ...);
中以在 MainThread 中执行此操作,因此您View
会收到更改通知。
HIH
推荐阅读
- java - 如何将模拟注入到从测试类下降两步的方法中
- php - 角 6 CSV 下载
- typescript - 打字稿,相同的类但不同的属性类型?
- python - 基于现有列值的新列
- ios - Setting up a ViewController for a .xib view
- php - PHP通过单击按钮从表中删除行
- android - Is it possible set the address outside the code, in config file in xamarin android?
- javascript - 我想从关联数组中只打印一次重复的值
- android - load previous comments in firebase firestore not work as expected in anrdoid
- angular - how to get firebase document as a angular object model