当我绑定ListView到ReactiveList时,ListView在几秒钟后停止更新



我正在开发一个应用程序与Xamarin。窗体,试图利用ReactiveUI,但Xamarin。Forms ListView的行为不符合预期。

测试设置是一个输入字段,我在其中输入值。我订阅了ReactiveList上的更改,并将值添加到ListView中。

问题:ListView更新了几秒钟,然后就停止了。

示例代码:

<!-- xaml layouts omitted for brevity -->         
      <Entry x:Name="searchbox" HorizontalOptions="FillAndExpand"
             Text="{Binding SearchQuery, Mode=TwoWay}"
         />
      <ListView x:Name="ResultView">
        <ListView.ItemTemplate>
          <DataTemplate>
            <TextCell Text="{Binding Address}"></TextCell>
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>

ViewModel + SearchResult类:

public class SearchViewModel : ReactiveObject
{
    public ReactiveList<SearchResult> SearchResults { get; set; }
    private string searchQuery;
    public string SearchQuery
    {
        get { return searchQuery; }
        set { this.RaiseAndSetIfChanged(ref searchQuery, value); }
    }
    public ReactiveCommand<List<SearchResult>> Search { get; set; }

    public SearchViewModel()
    {
        // Set up our ListView data list
        this.SearchResults = new ReactiveList<SearchResult>();
        this.SearchResults.ChangeTrackingEnabled = true;
        Search = ReactiveCommand.CreateAsyncTask(async _ => {
            return await GenerateSearchResultAsync(this.SearchQuery);
        });
        Search.Subscribe(results => {
            SearchResults.Clear(); // just replace output every time
            SearchResults.AddRange(results);
            // output results to console
            results.ForEach(r => Console.WriteLine(r.Address));
        });
        // this used to contain a condition I removed for brevity
        this.WhenAnyValue(x => x.SearchQuery).InvokeCommand(this, x => x.Search);
    }
    // create a new result list and return it, async code removed for demo-simplicity
    private static async Task<List<SearchResult>> GenerateSearchResultAsync(string value)
    {
        var rv = new List<SearchResult>();
        rv.Add(new SearchResult(value + " " + DateTime.Now.ToString("hh:mm:ss.FFFF")));            
        return rv;
    }
}
public class SearchResult
{
    private string address;
    public SearchResult(string s)
    {
        this.Address = s;
    }
    public string Address { get; set; }
}

这似乎是在GC期间错误地收集WeakReferences的错误。我没有足够的知识来做调试,但是其他一些聪明的人做了:

https://github.com/reactiveui/ReactiveUI/issues/806

https://bugzilla.xamarin.com/show_bug.cgi?id=31415(打开xamarin bug报告)

处理:

将这个类添加到您的项目中:

public class ReactiveObservableCollection<T> : ReactiveList<T> 
{
    public ObservableCollection<T> ObservableCollection { private set; get; }
    public ReactiveObservableCollection()
    {
        this.ObservableCollection = new ObservableCollection<T>();
        ItemsAdded.Subscribe(ObservableCollection.Add);
        ItemsRemoved.Subscribe((x) => ObservableCollection.Remove(x));
    }
}

并使用它来代替ReactiveList:

public class ViewModel : ReactiveObject {
public ReactiveObservableCollection<SearchResult> SearchResults { set; get; }
public ViewModel() 
{
     // use ReactiveObservableCollection instead of ReactiveList
     this.SearchResults = new ReactiveObservableCollection<SearchResult>()
     {
        ChangeTrackingEnabled = true
     };
}

另外,确保在集合上使用.ObservableCollection属性作为ItemSource(而不仅仅是集合)!

this.ResultView.ItemsSource = viewModel.SearchResults.ObservableCollection;
不是

this.ResultView.ItemsSource = viewModel.SearchResults;

这应该能解决问题。

HTH !

相关内容

  • 没有找到相关文章

最新更新