2016-06-30 6 views
0

Xamarin.FormsでReactiveUIを利用しようとするとアプリケーションを開発していますが、Xamarin.Forms ListViewが期待通りに動作しません。ListViewをリアクティブリストにバインドすると数秒後に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; } 
} 

答えて

1

これはWeakReferencesが誤っGC中に収集されたときのバグのようです。 私がデバッグを行うのに十分な知力ないんだけど、いくつかの他のスマート連中がやった:

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

https://bugzilla.xamarin.com/show_bug.cgi?id=31415(オープンxamarinのバグ報告を)

回避策:

このクラスを追加します。あなたのプロジェクトに:

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の代わりにそれを使用するd次の

public class ViewModel : ReactiveObject { 

public ReactiveObservableCollection<SearchResult> SearchResults { set; get; } 

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

また、(だけでなく、コレクションの)ItemSourceとしてコレクションに.ObservableCollectionプロパティを使用してください!

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

代わりに

this.ResultView.ItemsSource = viewModel.SearchResults。

これは問題を解決するはずです。

HTH!

関連する問題