2011-05-22 74 views
1

在MVVM項目中有一個ViewModel綁定到一個WPFView,該WPFView包含一個列表框,在該列表框中開始搜索時將異步加載數據。 我的搜索返回的數據包含在不同日子購買的相同商品的價格。 我需要我的列表框中的項目按價格排序:我的BackgroundWorker儘快返回項目,這些項目會異步添加到我的列表框中,並按價格排序,讓我儘快查看最佳價格。在MVVM運行時將ObservableCollection <T>中的WPF ListBox ItemsSource切換到CollectionViewSource

我發現的更好的解決方案是在我的ViewModel中有一個ObservableCollection並將其綁定到我的ListBox的ItemsSource 我有一個BackgroundWorker來啓動異步搜索;我訂閱了進行搜索對象的DataReceived事件處理程序,並通知我這樣的用戶界面:通過

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

一個調度

private readonly Dispatcher _currentDispatcher; 

這似乎沒給我,但不按我需要的順序排列項目,所以我發現CollectionViewSource完全符合我需要的簡單方法。

這就是問題所在:

如果我把我的列表框到CollectionViewSource少我設計時電源的DataContext的,我總是看到在我的列表框我的設計時間的數據,但我失去的DataContext在數據Blend選項卡。

所以我做了一些我認爲有點髒的事情: 我用ax:Name屬性命名我的ListBox,並在我的MainWindow.xaml中添加了一些代碼,以便在運行時交換我命名的listbox的數據源,就像這樣的:

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 
    } 

你認爲這也算是一種罪過?

+0

如果這對你很好,讓你開心,我不明白爲什麼你會認爲它是一個「罪」;) – AbdouMoumen 2011-05-22 20:32:05

回答

1

您可以將collectionview的源代碼綁定到observablecollecion。我的問題是:如果你正在使用mvvm,你爲什麼要做所有這些看起來像代碼隱藏?

視圖模型構造:

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的人的帖子,但沒有使用它的一些最強大的功能。如果您將其用作其設計用途,則它的工作原理與其應用一樣......我可以證實這一點。

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

我相信IsDataSource屬性告訴Blend將它放在DataTab上...但是我不會爲我的Datamanipulations使用混合,所以我並不擔心它。

相關問題