gpt4 book ai didi

listview - 在 Xamarin 表单中将 ReactiveList 绑定(bind)到 ListView

转载 作者:行者123 更新时间:2023-12-03 06:26:00 28 4
gpt4 key购买 nike

我觉得我的做法是正确的,但我不确定。我正在将对象异步加载到 ViewModel 中的 ReactiveList 中。通过 Xamarin Forms,我已将 List 绑定(bind)到 Xamarin Forms 中 ListView 的 ItemSource 属性。我还有一个搜索框,它将清除 ReactiveList 并向 ReactiveList 添加新项目。

第一次打开 View 时,没有交互使列表加载,并且绑定(bind)到 ReactiveCommand 的用于将更多项目加载到 ReactiveList 的按钮被禁用。

我第二次打开 View 时,ListView 几乎立即渲染新 ViewModel 中的项目,但同样,交互似乎不起作用。但是,更改搜索框实际上会从 ListView 中清除项目,但不会添加项目。

此行为发生在 iOS 上。我是 ReactiveUI 6.3.1 和 Xamarin Forms 1.3.2.6316。

这是简化的问题:

public class MyViewModel : ReactiveObject, IRoutableViewModel
{
public MyViewModel(IScreen hostScreen = null)
{
HostScreen = hostScreen ?? Locator.Current.GetService<IScreen>();

List = new ReactiveList<ItemViewModel>()
{
ChangeTrackingEnabled = true
};

//This never gets shown
List.Add(new ItemViewModel()
{
Name = "TEST"
});

//Tried doing this on the main thread: same behavior
LoadItemsCommand = ReactiveCommand.CreateAsyncTask(_ => GetItems()), RxApp.TaskpoolScheduler);

LoadItemsCommand
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(results =>
{
//debugger breaks here in EVERY case and successfully changes List but doesn't necessarily affect the view

try
{
List.AddRange(results.Select(e => new ItemViewModel()
{
Name = e.Name
}));
}
catch (Exception ex)
{
//breakpoint does not break here.
Debug.WriteLine(ex.Message);
throw;
}

});

//No exceptions here either
LoadItemsCommand.ThrownExceptions
.Select(ex => new UserError("Error", "Please check your Internet connection"))
.Subscribe(Observer.Create<UserError>(x => UserError.Throw(x)));

this.WhenAnyValue(e => e.SearchText).Subscribe(e => ResetPage());
}

private Task<IEnumerable<Item>> GetItems()
{
//asynchronously get items
return ...;
}

private int ResetPage()
{
List.Clear();
return 0;
}

[DataMember]
public ReactiveList<ItemViewModel> List { get; private set; }

private string _searchText;
[DataMember]
public string SearchText
{
get { return _searchText; }
set { this.RaiseAndSetIfChanged(ref _searchText, value); }
}

public ReactiveCommand<IEnumerable<Item>> LoadItems { get; protected set; }

public class ItemViewModel : ReactiveObject
{
public string Name { get; set; }
}

public string UrlPathSegment
{
get { return "Page"; }
}

public IScreen HostScreen { get; protected set; }


}

我的xaml:

  <StackLayout VerticalOptions="FillAndExpand" Orientation="Vertical">
<Entry x:Name="_searchEntry" Placeholder="Search"></Entry>
<ListView x:Name="_myListView" RowHeight="80">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" >
<Label Text="{Binding Name}"></Label>
<Label Text="{Binding Address}"></Label>
<Label Text="{Binding PhoneNumber}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button x:Name="_loadMoreButton" Text="Load More" TextColor="White" BackgroundColor="#77D065"></Button> </StackLayout>
</XamForms:ReactiveContentPage>

我的 View 代码隐藏:

using System;
using System.Reactive.Concurrency;
using System.Threading.Tasks;

using ReactiveUI;
using ReactiveUI.XamForms;

namespace views
{
public partial class MyView : ReactiveContentPage<MyViewModel>
{
private IDisposable _disconnectHandler;

public NearbyPlacesView()
{
InitializeComponent();

this.Bind(this.ViewModel, model => model.SearchText, view => view._searchEntry.Text);
this.OneWayBind(this.ViewModel, model => model.List, view => view._myListView.ItemsSource);
this.BindCommand(this.ViewModel, model => model.LoadItemsCommand, view => view._loadMoreButton);
}

protected override void OnAppearing()
{
base.OnAppearing();

//Is this the proper way to do this? seems
_disconnectHandler = UserError.RegisterHandler(async error =>
{
RxApp.MainThreadScheduler.ScheduleAsync(async (scheduler, token) =>
{
await DisplayAlert("Error", error.ErrorMessage, "OK");
});

return RecoveryOptionResult.CancelOperation;
});

//Load the items when the view appears. This doesn't feel right though.
ViewModel.LoadItemsCommand.Execute(null);
}

protected override void OnDisappearing()
{
base.OnDisappearing();

_disconnectHandler.Dispose();
_disconnectHandler = null;
}
}
}

最佳答案

这似乎是 Xamarin Forms 或 ReactiveUI 的错误。该问题记录在此处:https://github.com/reactiveui/ReactiveUI/issues/806

我更改了 public ReactiveList<ItemViewModel> List 的类型至public ObservableCollection<ItemViewModel> List这解决了问题。

关于listview - 在 Xamarin 表单中将 ReactiveList<T> 绑定(bind)到 ListView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28383734/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com