我在一个MVVM项目中有一个ViewModel,它绑定到一个WPFView,它包含一个列表框,在这个列表框中,当你开始搜索时异步加载数据。 我的搜索返回的数据包含在不同日期购买的相同商品的价格。 我需要按列表升序列出我的列表框中的项目:一旦我的BackgroundWorker返回项目,这些项目就会异步添加到我的列表框中并按价格排序,让我看到最快的价格。
我找到的更好的解决方案是在我的ViewModel中有一个ObservableCollection并将它绑定到我的ListBox的ItemsSource 我有一个启动异步搜索的BackgroundWorker;我订阅了进行搜索的对象的DataReceived EventHandler,我按这样通知用户界面:
void sniper_DataReceived(object sender, TEventArgs e)
{
Action dispatchAction = () => this.Results.Add(e.T);
_currentDispatcher.BeginInvoke(dispatchAction);
}
通过Dispatcher
private readonly Dispatcher _currentDispatcher;
这对我来说似乎没问题,但是没有按照我的需要订购这些项目,所以我发现CollectionViewSource正是我所需要的,只是简单的方式。
这是问题所在:
如果我将listbox的datacontext设置为CollectionViewSource,我的设计时间能力较小,我会在列表框中看到我的设计时数据,但是我在Blend的Data选项卡中丢失了DataContext。
所以我做了一些我认为有点脏的事情: 我使用x: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
}
你认为这可以被视为罪吗?
答案 0 :(得分:1)
您可以将集合视图的源绑定到observablecollecion。我的问题是:如果你正在使用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但没有使用其中一些最强大功能的帖子。如果你使用它作为它的设计使用,它的工作就像它应该工作......我可以证明这一点。
<!--Global View Model Locator-->
<local:ViewModelLocator x:Key="Locator"
d:IsDataSource="True" />
我相信IsDataSource属性告诉Blend将它放在DataTab上......但我不会使用混合这么多来进行我的Datamanipulations所以我并不担心它。