将SelectedItem从另一个NavPage的ListView绑定到根NavPage UI不起作用



我想使用右边的NavBar按钮作为ListView的过滤函数。我的第一种方法是下拉列表,但由于这在iOS中是不可能的,我试图用NuGet包Rg.Plugins.Popup绕过它(我不想创建CustomRenderer(。到目前为止一切都很顺利。

从其他ListView中选择后,我的UI不会更新。关于调试,我的值正确更改。

这是我的ViewModel:

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>

现在这是我的弹出页面,位置为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编辑。用户对话框:

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)

ViewModel:中注入IUserDialog

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属性,所以你必须将该设置包装在Xamarin.Forms.Device.BeginInvokeOnMainThread(() => ...);中才能在主线程上完成,这样你的View就会收到更改通知。

HIH-

它不是下拉列表,但您也可以只使用ActionSheet(如果您不知道的话(。我只是建议它,因为它非常简单可靠,我知道它没有下拉列表那么漂亮(但它也可能比下拉列表更漂亮(。

最新更新