1

次の(レガシー)例に基づいて、WPF MVVMアプリケーション内にReactiveUI非同期検索ルーチンの実用的な実装があります。

http://blog.paulbetts.org/index.php/2010/07/05/reactivexaml-series-implementing-search-with-observableaspropertyhelper/

public class TheViewModel : ReactiveObject
{
    private string query;

    private readonly ObservableAsPropertyHelper<List<string>> matches;

    public TheViewModel()
    {
        var searchEngine = this.ObservableForProperty(input => input.Query)
                .Value()
                .DistinctUntilChanged()
                .Throttle(TimeSpan.FromMilliseconds(800))
                .Where(query => !string.IsNullOrWhiteSpace(query) && query.Length > 1);

        var search = searchEngine.SelectMany(TheSearchService.DoSearchAsync);

        var latestResults =
            searchEngine.CombineLatest(search, (latestQuery, latestSearch) => latestSearch.Query != latestQuery ? null : latestSearch.Matches)
                .Where(result => result != null);

        matches = latestResults.ToProperty(this, result => result.Matches);
    }

    public string Query
    {
        get
        {
            return query;
        }
        set
        {
            this.RaiseAndSetIfChanged(ref query, value);
        }
    }

    public List<string> Matches
    {
        get
        {
            return matches.Value;
        }
    }
} 

ReactiveXAML は期待どおりに機能しており、Matches プロパティに簡単にバインドできます。

<ListBox Grid.Row="1" Margin="6" ItemsSource="{Binding Matches}" />

ただし、次のようなより複雑な結果構造を返すように TheSearchService.DoSearchAsync() をリファクタリングしたいと思います。

public class SearchResult
{
    public string Query { get; set; }
    public List<string> Matches { get; set; }
    public int MatchCount { get; set; }
    public double SearchTime { get; set; }
}

一致は引き続き として表されList<string>、同じ ListBox にバインドされますが、次のような形式で一致数と検索時間を返す各検索の文字列メタデータ プロパティにもバインドしたいと思います。

 string.Format("Found {0} matches in {1}s", x.MatchCount, x.SearchTime)

ViewModel の実装を変更して、検索ごとに複数のバインドを許可するにはどうすればよいですか?

受け入れられた回答に基づく実用的な実装

public class TheViewModel : ReactiveObject
{
    ...

    private readonly ObservableAsPropertyHelper<SearchResult> results;

    public TheViewModel()
    {
        ...

        var latestResults = searchEngine.CombineLatest(search, (latestQuery, latestSearch) => latestSearch.Query != latestQuery ? null : latestSearch)
                .Where(result => result != null);

        results = latestResults.ToProperty(this, result => result.Result);
    }

    ...

    public SearchResult Result
    {
        get
        {
            return results.Value;
        }
    }
}

これがビューです

<StackPanel>
    <TextBox Text="{Binding Query, UpdateSourceTrigger=PropertyChanged}"
             Margin="6"
             FontSize="26" />
    <TextBlock>
        <TextBlock.Text>
            <MultiBinding StringFormat="Found {0} matches in {1}s">
                <Binding Path="Result.MatchCount" />
                <Binding Path="Result.SearchTime" />
            </MultiBinding>
        </TextBlock.Text>
    </TextBlock>
</StackPanel>
<ListBox Grid.Row="1"
     Margin="6"
     ItemsSource="{Binding Result.Matches}" />
4

1 に答える 1