2016-04-15 9 views
0

Nur um das heraus zu bekommen - Ich bin ein kompletter Neuling bei XAML, Univeral Apps und ReactiveUI, so vermisse ich hier wahrscheinlich etwas Einfaches.ListBox nicht in UWP mit ReactiveUI

Um ReactiveUI in den Griff zu bekommen, dachte ich, ich würde versuchen, das ReactiveUI WPF Flickr-Beispiel aus der Dokumentation (Reactive UI 101) in eine Windows Universal App zu portieren. Ich verwende Visual Studio 2015, ReactiveUI 6.5 mit aktualisiertem Splat.

Ich kopierte den Code und machte die notwendigen Änderungen, damit es für UWP kompilieren. Der aktuelle Code wird kompiliert und geöffnet, funktioniert jedoch nicht ordnungsgemäß.

Ich habe zwei Fragen:

  1. Ich habe außerhalb der Suche klicken: Feld der Flickr-Fotos Suche zu treten. Von dem, was ich verstanden habe, sollte ich nicht wegklicken müssen, es sollte nur darauf warten, dass ich etwas eingegeben habe und die Suche nach der Zeitüberschreitung von 800ms abgebrochen habe. Das Debuggen der Fotosuche funktioniert und eine Sammlung von Objekten wird als meine SearchResults zurückgegeben.

  2. Das zweite Problem ist, dass, obwohl ich eine Liste der Ergebnisse bekomme, die ListBox nie ausgefüllt wird. Ich habe versucht, die Bindung, wie im Beispiel gezeigt, und auch mit x: Bind, wie ich in allen UWP-Tutorials gelernt habe - ohne Würfel.

heruntergeladen ich eine andere UWP Probe (RxUI and UWP .Net Native Sample) und bin auf der Suche in seiner Struktur und das Setup zu sehen, was ich verpasst, aber es ist ein bisschen komplizierter jetzt zu mir.

Wenn mir jemand in die richtige Richtung zeigen könnte, würde es sehr helfen.

Hier ist meine XAML:

<Page 
x:Class="ReactiveUIFlickerApp.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="using:ReactiveUIFlickerApp" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:data="using:ReactiveUIFlickerApp.Models" 
x:Name="MainPageView" 
mc:Ignorable="d"> 

<Page.Resources> 
    <DataTemplate x:Key="PhotoDataTemplate" 
        x:DataType="data:FlickrPhoto"> 
     <Grid MaxHeight="100"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto" /> 
       <ColumnDefinition Width="*" /> 
      </Grid.ColumnDefinitions> 

      <Image Source="{x:Bind Url, Mode=OneWay}" Margin="6" MaxWidth="128" 
        HorizontalAlignment="Center" VerticalAlignment="Center" /> 

      <StackPanel Grid.Column="1" Margin="6"> 
       <TextBlock FontSize="14" FontWeight="Bold" Text="{x:Bind Title}" /> 
       <TextBlock FontStyle="Italic" Text="{x:Bind Description}" 
          TextWrapping="Wrap" Margin="6" /> 
      </StackPanel> 
     </Grid> 
    </DataTemplate> 
</Page.Resources> 

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" 
     Margin="12"> 

    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="Auto" /> 
    </Grid.ColumnDefinitions> 

    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 

    <TextBlock FontSize="16" 
       FontWeight="Bold" 
       VerticalAlignment="Center">Search For:</TextBlock> 

    <TextBox Grid.Column="1" 
      Margin="6,0,0,0" 
      Text="{x:Bind PageViewModel.SearchTerm, Mode=TwoWay}"/> 

    <TextBlock Grid.Column="2" 
       Margin="6,0,0,0" 
       FontSize="16" 
       FontWeight="Bold" 
       Text="..." 
       Visibility="{x:Bind PageViewModel.SpinnerVisibility}" /> 

    <ListBox Grid.ColumnSpan="3" 
      Grid.Row="1" 
      Margin="0,6,0,0" 
      ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
      ItemsSource="{x:Bind PageViewModel.SearchResults, Mode=OneWay}" 
      ItemTemplate="{StaticResource PhotoDataTemplate}" /> 
</Grid> 

Der XAML-Code-behind:

public sealed partial class MainPage : Page 
{ 
    public MainPageViewModel PageViewModel { get; private set;} 

    public MainPage() 
    { 
     PageViewModel = new MainPageViewModel(); 

     this.InitializeComponent(); 
    } 
} 

Die MainPageViewModel (in einem eigenen Ordner anzeigen in der Lösung):

public class MainPageViewModel : ReactiveObject 
{ 
    string _SearchTerm; 
    public string SearchTerm 
    { 
     get { return _SearchTerm; } 
     set { this.RaiseAndSetIfChanged(ref _SearchTerm, value); } 
    } 

    public ReactiveCommand<List<FlickrPhoto>> ExecuteSearch { get; protected set; } 

    ObservableAsPropertyHelper<List<FlickrPhoto>> _SearchResults; 
    public List<FlickrPhoto> SearchResults => _SearchResults.Value; 

    ObservableAsPropertyHelper<Visibility> _SpinnerVisibility; 
    public Visibility SpinnerVisibility => _SpinnerVisibility.Value; 



    public MainPageViewModel() 
    { 
     ExecuteSearch = 
      ReactiveCommand.CreateAsyncTask(parameter => GetSearchResultsFromFlickr(this.SearchTerm)); 


     this.WhenAnyValue(x => x.SearchTerm) 
      .Throttle(TimeSpan.FromMilliseconds(800), RxApp.MainThreadScheduler) 
      .Select(x => x?.Trim()) // null conditional operator 
      .DistinctUntilChanged() 
      .Where(x => !String.IsNullOrWhiteSpace(x)) 
      .InvokeCommand(ExecuteSearch); 

     _SpinnerVisibility = ExecuteSearch.IsExecuting 
      .Select(x => x ? Visibility.Visible : Visibility.Collapsed) 
      .ToProperty(this, x => x.SpinnerVisibility, Visibility.Collapsed/*Hidden*/); 

     ExecuteSearch.ThrownExceptions.Subscribe(ex => { Debug.WriteLine(ex.ToString());/* Handle errors here */}); 

     _SearchResults = ExecuteSearch.ToProperty(this, x => x.SearchResults, new List<FlickrPhoto>()); 
    } 

    public static async Task<List<FlickrPhoto>> GetSearchResultsFromFlickr(string searchTerm) 
    { 

     var client = new HttpClient(); 
     var stream = await client.GetStreamAsync(String.Format(CultureInfo.InvariantCulture, 
      "http://api.flickr.com/services/feeds/photos_public.gne?tags={0}&format=rss_200", 
      WebUtility.UrlEncode(searchTerm))); 

     //var doc = await Task.Run(() => XDocument.Load(String.Format(CultureInfo.InvariantCulture, 
     // "http://api.flickr.com/services/feeds/photos_public.gne?tags={0}&format=rss_200", 
     // WebUtility.UrlEncode(searchTerm)))); 

     var doc = await Task.Run(() => XDocument.Load(stream)); 

     if (doc.Root == null) 
      return null; 

     var titles = doc.Root.Descendants("{http://search.yahoo.com/mrss/}title") 
      .Select(x => x.Value); 

     var tagRegex = new Regex("<[^>]+>", RegexOptions.IgnoreCase); 
     var descriptions = doc.Root.Descendants("{http://search.yahoo.com/mrss/}description") 
      .Select(x => tagRegex.Replace(WebUtility.HtmlDecode(x.Value), "")); 
      //.Select(x => tagRegex.Replace(HttpUtility.HtmlDecode(x.Value), "")); 

     var items = titles.Zip(descriptions, 
      (t, d) => new FlickrPhoto { Title = t, Description = d }).ToArray(); 

     var urls = doc.Root.Descendants("{http://search.yahoo.com/mrss/}thumbnail") 
      .Select(x => x.Attributes("url").First().Value); 

     var ret = items.Zip(urls, (item, url) => { item.Url = url; return item; }).ToList(); 
     return ret; 
    } 
} 

Antwort

0

Wie ich erwähnt in meiner Antwort auf your issue on Github, aktualisiert UWP nicht TextBox Bindings, bis die Kontrolle den Fokus verliert. Sie müssen die RxUI Bind Familie verwenden, um das zu umgehen.

Was den Ergebnisliste, ich bin nicht genau sicher, warum es nicht außer arbeiten, dass ich auf einen ReactiveList<T> Bindung wäre (oder wahrscheinlicher, IReadOnlyReactiveList<T>). Anstatt List<T> zu zerstören, die ListBox.ItemsSource gebunden ist, wird INotifyPropertyChanged verwenden.

Sobald Sie das funktioniert, versuchen Sie, die Liste Bevölkerung in den Körper der ReactiveCommand Arbeiter, die in der Regel besser arbeiten wird.

+0

Danke, ich versuche immer noch herauszufinden, wo die Änderungen vorgenommen werden, sich in den Konzepten und dem syntaktischen Zucker verlieren ... wird Sie auf dem Laufenden halten. – SheriSteeves