1

検索を開始するとデータが非同期に読み込まれるリストボックスを含む WPFView にバインドされた MVVM プロジェクトに ViewModel があります。私の検索結果のデータには、別の日に購入された同じ商品の価格が含まれています。リストボックス内のアイテムを価格の昇順で並べる必要があります。BackgroundWorker がアイテムを返すとすぐに、アイテムがリストボックスに非同期に追加され、価格順に並べ替えられます。これにより、最高の価格が見つかるとすぐに表示されます。

私が見つけたより良い解決策は、ViewModel に ObservableCollection を配置し、それを ListBox の ItemsSource にバインドすることです。非同期検索を開始する BackgroundWorker があります。検索を行うオブジェクトの DataReceived EventHandler にサブスクライブし、次のように UI に通知します。

void sniper_DataReceived(object sender, TEventArgs e)
    {
        Action dispatchAction = () => this.Results.Add(e.T);
        _currentDispatcher.BeginInvoke(dispatchAction);
    }

ディスパッチャ経由

private readonly Dispatcher _currentDispatcher;

これは私には問題ないように思えますが、必要に応じてアイテムを注文しないため、 CollectionViewSource が必要なことを簡単な方法で正確に実行することがわかりました。

ここに問題があります:

リストボックスのデータ コンテキストを CollectionViewSource に設定すると、設計時の処理能力が低下します。リスト ボックスに設計時のデータが表示され続けますが、Blend の [データ] タブで DataContext が失われます。

だから私は少し汚れていると思うことをしました: ax:Name 属性で ListBox に名前を付け、MainWindow.xaml にコードを少し追加して、実行時に名前付きリストボックスのデータソースを次のように交換しました。

public MainWindow()
    {
        InitializeComponent();
        Closing += (s, e) => ViewModelLocator.Cleanup();

        #region CollectionViewSource Escamotage
        if (!ViewModelLocator.MainStatic.IsInDesignMode)
        {
            var cvs = new CollectionViewSource() { Source = ViewModelLocator.MainStatic.Results };
            cvs.SortDescriptions.Add(new SortDescription("LowestPrice", ListSortDirection.Ascending));
            this.TrainsListBox.ItemsSource = cvs.View; 
        }
        #endregion
    }

それは罪とみなすことができると思いますか。

4

1 に答える 1

1

コレクションビューのソースを観察可能なコレクションにバインドできます。私の質問は: mvvm を使用している場合、なぜ分離コードのように見えるものでこれらすべてを行っているのですか?

ViewModel コンストラクター:

 public PrimarySearchViewModel()
            {
                this.SearchResultsCVS = new CollectionViewSource();

                if (IsInDesignMode)
                {
                    DesignMode_CreateSearchResults();

                    // Code runs in Blend --> create design time data.
                }
                else
                {
                    //Messenger.Default.Register<IEnumerable<ReadmitPatientList>>(this, MessageTypes.EXECUTESEARCHREQUEST, RefreshSearchResults);
                    //Messenger.Default.Register<MessageTypes.EXECUTESEARCHREQUEST>>(this,ICollection<ReadmitPatientList>,RefreshSearchResults);
                    Messenger.Default.Register<Messages.DisplayReadmitPatientListMessage>(this, onReciveDisplayReadmitPatientListMessage);
                    Messenger.Default.Register<WavelengthIS.Core.Messaging.SaveNotification<QuestionairreViewModel>>(this, sn => ClearSearchResults());
                    // Code runs "for real": Connect to service, etc...
                }

            }

私は通常、デザインタイム サービスを使用してデザインタイム データを作成します。

private void DesignMode_CreateSearchResults()
            {
                this.SearchResults = new ObservableCollection<ReadmitPatientListViewModel>();

                this.SearchResults.Add(new ReadmitPatientListViewModel(new ReadmitPatientList()
                {
                    PatientID = 0000000,
                    PatientName = "Test Patient",
                    PatientDOB = Convert.ToDateTime("01/01/2010"),
                    OriginalAdmitDate = Convert.ToDateTime("01/01/2010 00:00:00"),
                    OriginalReason = "Becauselkahsdfkahsfkahsf",
                    OriginalVisitNumber = "0000000",
                    ReAdmitDate = Convert.ToDateTime("01/01/2010 00:00:00"),
                    ReAdmitReason = ";aasfkahsfashfa;lsfas",
                    ReAdmitVisitNumber = "9999999"
                }
                   ));
                this.SearchResults.Add(new ReadmitPatientListViewModel(new ReadmitPatientList()
                {
                    PatientID = 0000000,
                    PatientName = "Test Patient",
                    PatientDOB = Convert.ToDateTime("01/01/2010"),
                    OriginalAdmitDate = Convert.ToDateTime("01/01/2010 00:00:00"),
                    OriginalReason = "Becauselkahsdfkahsfkahsf",
                    OriginalVisitNumber = "0000000",
                    ReAdmitDate = Convert.ToDateTime("01/01/2010 00:00:00"),
                    ReAdmitReason = ";aasfkahsfashfa;lsfas",
                    ReAdmitVisitNumber = "9999999"
                }
                   ));
                this.SearchResults.Add(new ReadmitPatientListViewModel(new ReadmitPatientList()
                {
                    PatientID = 0000000,
                    PatientName = "Test Patient",
                    PatientDOB = Convert.ToDateTime("01/01/2010"),
                    OriginalAdmitDate = Convert.ToDateTime("01/01/2010 00:00:00"),
                    OriginalReason = "Becauselkahsdfkahsfkahsf",
                    OriginalVisitNumber = "0000000",
                    ReAdmitDate = Convert.ToDateTime("01/01/2010 00:00:00"),
                    ReAdmitReason = ";aasfkahsfashfa;lsfas",
                    ReAdmitVisitNumber = "9999999"
                }
                   ));

                SearchResultsCVS_Refresh();
            }
private void SearchResultsCVS_Refresh()
        {
            SearchResultsCVS.Source = this.SearchResults;
            SearchResultsCVS.SortDescriptions.Clear();

            SearchResultsCVS.SortDescriptions.Add(new System.ComponentModel.SortDescription("PatientLastName", System.ComponentModel.ListSortDirection.Ascending));

            SearchResultsCVS.View.Refresh();
        }

ViewModels の ObservableCollections を使用します。OC の通知イベントは、コレクションに追加または削除されたアイテムに対してのみ発生します。実際のリスト アイテムの vm を使用して、必要に応じてアイテム プロパティの変更通知を取得します。

また、ViewModelLocator がセットアップされ、正しく定義されていることを確認する必要があります。MVVMLight を使用しているが、MVVMLight の最も強力な機能の一部を使用していない人々の投稿をいくつか見つけました。使用するように設計されたとおりに使用すると、本来のように機能します...私はそれを証明できます.

 <!--Global View Model Locator-->
                    <local:ViewModelLocator x:Key="Locator"
                                            d:IsDataSource="True" />

IsDataSource 属性は Blend にそれを DataTab に配置するように指示していると思います...しかし、私は Datamanipulation にあまり Blend を使用していないので、それほど心配していません。

于 2011-05-29T12:25:36.823 に答える