0

ViewModelで監視可能なコレクションを注文するのに問題があります。これが私の状況です:

私のビューモデルには、次のリストがあります。

public List<TicketModel> Tickets
        {
            get { return _Tickets.Value; }
            set
            {
                {
                    this.RaiseAndSetIfChanged(c => c.Tickets, value);
                }
            }
        }
        private ObservableAsPropertyHelper<List<TicketModel>> _Tickets;

このリストは、ReactiveAsyncCommand:を使用して入力されます。

LoadTickets.RegisterAsyncFunction(x => loadTickets())
                .ToProperty(this, x => x.Tickets);

これまでのところすべてが機能します。

別のコマンドがSortByCommandあります。このコマンドは、ユーザーがコレクションを並べ替えるたびに呼び出されます。コマンドは次のようになります。

SortByCommand = new ReactiveCommand(this.WhenAny(c => c.Tickets, ((tickets) => tickets.Value != null && tickets.Value.Count > 0)));
SortByCommand.Subscribe(c => sortTickets((SortByModel)c));

このコマンドは、orderby句を使用してコレクションを順序付ける関数も呼び出します。

private void sortTickets(SortByModel model)
{
    Tickets = Tickets.OrderBy(model.Selector).ToList();
}

関数が呼び出されるたびに、次のsortTicketsような例外がスローされます。

Unable to cast object of type 'ReactiveUI.ObservableAsPropertyHelper`1[System.Collections.Generic.List`1[Bugmine.Modules.MyPage.Models.TicketModel]]' to type 'System.Collections.Generic.List`1[Bugmine.Modules.MyPage.Models.TicketModel]'.

いくつか質問があります。

Tickets1)モデルを直接設定できないのはなぜですか?OrderBy最初に、の結果をある種の観察可能なコレクションに変換する必要がありますか?

2)これを行うためのより良い方法はありますか?

編集:明確化

私が今取っているアプローチは次のとおりです。

  • コレクションはTicketsx秒ごとにリセットされます。
  • sortTickets関数が呼び出されるとすぐに、このコレクションを次のように並べ替えてリセットします。

    Tickets = Tickets.OrderBy(c => c.Name).ToList(); //for example

  • コレクションが再度読み込まれるときに、プロパティTicketsを設定する前に、コレクションを並べ替える必要があるかどうかを確認して並べ替えTicketsます。

私は基本的にコレクションをロード時とソート時の2つのポイントに設定しているので、これは少しハッキーな感じがします。さらに、ロード時にReactiveUIヘルパー-> ToPropertyを使用しています:

LoadTickets.RegisterAsyncFunction(x => loadTickets())
    .ToProperty(this, x => x.Tickets);

一方、並べ替えると、自分でそれを実行します。

Tickets = Tickets.OrderBy(model.Selector).ToList();

ロード時にすでに使用しているReactiveUIアプローチを使用してソートを行うためのより良い方法があるかどうか疑問に思っています。

前もって感謝します!

4

3 に答える 3

2

Anaのブログhttp://blog.paulbetts.org/index.php/2010/07/05/reactivexaml-series-implementing-search-with-observableaspropertyhelper/をご覧ください。

//
// This is the canonical way to make a read-only property whose value
// is backed by an IObservable
//

ObservableAsPropertyHelper<List<FlickrPhoto>> _Photos;

読み取り専用が重要なポイントだと思います。

代わりに、OnNextを使用して新しい値をプッシュできる通常のオブザーバブルを使用してみることができます

private Observable<List<TicketModel>> _Tickets = new Observable<Lis<TicketModel>>();
_Tickets.OnNext(newValue);

または、ObservableForProperty <>を使用して、通常どおりプロパティを使用します

public List<TicketModel> _Tickets { get;set;}
private Observable<List<TicketModel>> _ticketsObservable= ObservableForProperty<..>(x=>x.Tickets);

これらのメソッドは両方とも、後でソートで使用できるObservableを公開します。

ソートへの2つの入力を同じように処理してみてはどうでしょうか。そうすれば、それほどハックな感じはしません。そうすれば、

public SortModel SortModel {get;set;}

ソートコマンドの実装は次のようになります

SortByCommand.Subscribe(c => _Sort = c));

ただし、チケットの変更と並べ替え基準の変更の両方を1つにサブスクライブします。CombineLatestについては、http://rxwiki.wikidot.com/101samples#toc44を参照てください。

new ObservableForProperty<..>(x=>x.SortModel)
    .CombineLatest(_ticketsObservable) 
    .Subscribe( (x,y)=>
    {
         //Refactor to SortMethod
         _tickets = y.OrderBy(x.Selector);
    });
于 2013-01-28T14:05:34.100 に答える
2

これを解決する別の方法は、次の方法CreateDerivedCollectionです。

SortedTickets = Tickets.CreateDerivedCollection(
    x => new TicketViewModel(x),
    orderer: (l,r) => SortModel.Selector(l, r),  // Returns CompareTo() result
    signalReset: this.WhenAny(x => x.SortModel, x => x.Value));  // Reorder on SortModel change

Tickets繰り返し設定されている場合(この場合はそうです)、これは機能しなくなることに注意してください。モデルをTicketsctorで初期化してから、すべてのアイテムをクリアして追加するように変更できます。

LoadTickets.RegisterAsyncFunction(x => loadTickets())
    .Subscribe(x => {
        // TODO: Make sure Tickets is a ReactiveCollection
        Tickets.Clear();
        Tickets.AddRange(x);   // Will trigger resorting of SortedTickets
    });
于 2013-01-28T18:58:49.933 に答える
0
  1. OrderBy(..)の結果は、ObservableCollectionではなくIEnumerableであると確信しています。幸いなことに、変換を実行できるコンストラクターがあります。

Tickets = new ObservableCollection <...>(Tickets.OrderBy(...));

  1. 「より良い」は非常に主観的な尺度になり得ます。まず、Ticketsコレクションの全寿命とそれに含まれるチケットについて説明していないため、実際にはわかりません。チケットのプロパティを上書きする代わりに、SortedTicketsフィールド/プロパティを使用することを検討してください。これは、TicketsobservableからNotfyProperryChangedが必要な場合にわかるように、監視可能なコレクションである必要はない場合があります。それはすべて、チケットが変更される可能性が高い頻度によって異なります。

PSまた、別のチケットを追加するときに、ソートされたリストがどうなるかをテストしたことを確認してください。

于 2013-01-28T07:44:50.970 に答える