2015-02-07 13 views
5

में सूची दृश्य में मुझे लगता है कि मैं इसे सही तरीके से कर रहा हूं, लेकिन मुझे यकीन नहीं है। मैं ऑब्जेक्ट को अपने व्यूमोडेल में एक प्रतिक्रियाशील सूची में अतुल्यकालिक रूप से लोड कर रहा हूं। Xamarin फॉर्म के माध्यम से, मैंने Xamarin फॉर्म में ListView की ItemSource प्रॉपर्टी में सूची को बाध्य कर दिया है। मेरे पास एक खोज बॉक्स भी है जो प्रतिक्रियाशील सूची को साफ़ करेगा और प्रतिक्रियाशील सूची में नए आइटम जोड़ देगा।बाध्यकारी प्रतिक्रियाशील सूची <T> Xamarin फॉर्म

पहली बार जब मैं दृश्य खोलता हूं, कोई इंटरैक्शन सूची लोड नहीं करता है, और एक बटन जो प्रतिक्रियाशील सूची में अधिक आइटम लोड करने के लिए एक ReactiveCommand से जुड़ा हुआ है अक्षम है।

दूसरी बार जब मैं सूची दृश्य दृश्य खोलता हूं तो आइटम को लगभग तुरंत नए व्यूमोडेल में प्रस्तुत करता है, लेकिन फिर से, इंटरैक्शन काम नहीं कर रहे हैं। हालांकि, खोज बॉक्स को बदलना वास्तव में ListView से आइटम साफ़ करता है, लेकिन आइटम जोड़े नहीं जाते हैं।

यह व्यवहार आईओएस पर है। मैं ReactiveUI 6.3.1 और Xamarin फॉर्म 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> 

मेरा विचार कोड-पीछे:

यहाँ सरलीकृत समस्या है

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

मुझे प्रारंभिक परीक्षण प्रविष्टि प्रदर्शित होने के लिए मिला। इसका कारण यह था कि ResetPage() प्रारंभिक परीक्षण प्रविष्टि को साफ़ कर रहा था। – kmc059000

+0

मुझे बहुत कुछ पता चला। ViewModel कन्स्ट्रक्टर में कॉल का प्लेसमेंट महत्वपूर्ण है! मैंने LoadItemsCommand सेटअप से पहले SearchText के लिए 'यह .henAnyValue (...) 'स्थानांतरित किया। 'ResetPage()' अब 'LoadItemsCommand.Execute (null);' पर कॉल करता है और मैंने 'ViewItemsCommand.Execute (null); '' ViewAtpearing() 'से बाहर कोड कोड में बाहर निकाला। हालांकि मुझे अभी भी समस्या मिल रही है जहां पहली बार मैं पृष्ठ देखता हूं, कुछ भी प्रकट नहीं होता है। – kmc059000

उत्तर

4

इस के साथ एक बग हो रहा है या तो Xamarin फॉर्म या ReactiveUI। इस मुद्दे को यहां दस्तावेज किया गया है: https://github.com/reactiveui/ReactiveUI/issues/806

मैंने public ReactiveList<ItemViewModel> List से public ObservableCollection<ItemViewModel> List के प्रकार को बदल दिया जो इस मुद्दे को हल करता है।

+0

मैं इस मुद्दे पर बहुत हैरान हूं, ReactiveUI ने पिछले 2 - 3 वर्षों में इसकी स्थिरता से मुझे प्रभावित किया। – Felix

0

आपका आइटम व्यूमोडेल एक प्रतिक्रियाशील ऑब्जेक्ट है, हालांकि, आपने सेटटर को ठीक से कोड नहीं किया है। याद रखें, आपको इसका उपयोग करना चाहिए। एनपीसी बढ़ाने के लिए सेटर में रेज एंडसेट IfChanged।

+0

एक प्रतिक्रियाशील सूची <> संपत्ति के लिए आवश्यक नहीं है जब तक आप मूल को ओवरराइट करने के लिए नए नहीं होते। – kenny

+0

यह सुनिश्चित नहीं है कि यह क्यों आवश्यक नहीं है अगर यह स्पष्ट रूप से काम नहीं करता है? –

संबंधित मुद्दे