2015-02-07 28 views
5

Bunu doğru şekilde yapıyorum gibi hissediyorum, ama emin değilim. ViewModel'imde eşzamansız olarak bir ReactiveList'e nesne yüklüyorum. Xamarin Formları aracılığıyla, List'i Xamarin Formlarında bir ListView'in ItemSource özelliğine bağladım. Ayrıca ReactiveList'i temizleyecek ve ReactiveList'e yeni öğeler ekleyecek bir arama kutum var.Bağlama ReaktiviteList <T> Xamarin Formları içinde ListView için

İlk kez görünümü açtığımda, hiçbir etkileşim listeyi yüklemez ve ReactiveList'e daha fazla öğe yüklemek için ReactiveCommand'a bağlı olan bir düğme devre dışı bırakılır.

ListView'i görüntüle'yi ikinci kez açtığımda, yeni ViewModel'deki öğeleri neredeyse derhal işler, ancak yine de etkileşimler işe yaramaz. Ancak, arama kutusunun değiştirilmesi aslında ListView'den öğeleri temizler, ancak öğeler eklenmez.

Bu davranış, iOS üzerindedir. Ben ReactiveUI 6.3.1 ve Xamarin Formları 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; } 


} 

Benim 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> 

kod arkasında Bence: Burada

basitleştirilmiş bir sorundur

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; 
     } 
    } 
} 
+0

Görüntülenecek ilk test girişini aldım. Bunun sebebi, ResetPage() 'in ilk test girişini temizlemesiydi. – kmc059000

+0

Bunun birçoğunu anladım. ViewModel yapıcısında aramaların yerleştirilmesi önemlidir! LoadItemsCommand kurulumundan önce SearchText için 'this.WhenAnyValue (...)' yi taşıdım. 'ResetPage() şimdi' 'LoadItemsCommand.Execute (null);' ve 'ViewItemsCommand.Execute (null); Yine de, sayfayı ilk defa görüntülediğimde sorunu göremiyorum, hiçbir şey görünmüyor. – kmc059000

cevap

4

Bu bir hata gibi görünüyor ya Xamarin Formları veya ReactiveUI. Sorun burada belgelenmiştir: https://github.com/reactiveui/ReactiveUI/issues/806

Sorunu gideren public ReactiveList<ItemViewModel> List türünü public ObservableCollection<ItemViewModel> List olarak değiştirdim.

+0

Bu konuya çok şaşırdım, ReactiveUI son 2 - 3 yıl içindeki istikrarından beni etkiledi. – Felix

0

ItemViewModel ürününüz bir ReactiveObject ürünüdür, ancak ayarlayıcıyı doğru şekilde kodlamadınız. Unutmayın, bunu kullanmalısınız.RaiseAndSetIfNPC'yi yükseltmek için sette değiştirildi.

+0

Orijinalin üzerine yazılmadıkça bir ReactiveList <> özelliği için gerekli değildir. – kenny

+0

Açıkçası bu işe yaramadıysa neden gerekli olmadığından emin değil misiniz? –

İlgili konular