gpt4 book ai didi

wpf - 在运行时在 MVVM 中将 WPF ListBox ItemsSource 从 ObservableCollection 切换到 CollectionViewSource

转载 作者:行者123 更新时间:2023-12-03 10:40:16 25 4
gpt4 key购买 nike

我在一个绑定(bind)到 WPFView 的 MVVM 项目中有一个 ViewModel,该 WPFView 包含一个列表框,当您开始搜索时,该列表框会异步加载数据。
我的搜索返回的数据包含在不同日期购买的相同商品的价格。
我需要按价格升序对列表框中的项目进行排序:一旦我的 BackgroundWorker 返回项目,这些项目就会异步添加到我的列表框中并按价格排序,让我在捕获时看到最优惠的价格。

我发现更好的解决方案是在我的 ViewModel 中有一个 ObservableCollection 并将它绑定(bind)到我的 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 以一种简单的方式完全符合我的需要。

这就是问题所在:

如果我将列表框的 datacontext 设置为 CollectionViewSource,我的设计时间能力会降低,我会一直在列表框中看到我的设计时间数据,但我会在 Blend 的“数据”选项卡中丢失 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
}

你认为它可以被认为是一种罪过吗?

最佳答案

您可以将 collectionview 的源绑定(bind)到 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 的通知事件仅针对从集合中添加或删除的项目触发,通过使用实际列表项的虚拟机,如果需要,您可以获得项目属性的更改通知。

您还需要确保您的 ViewModelLocator 设置和定义正确。我现在发现了几篇关于人们使用 MVVMLight 但没有使用其中一些最强大功能的帖子。如果您按照设计使用它来使用它,它的工作原理就像它应该工作的那样......我可以证明这一点。
 <!--Global View Model Locator-->
<local:ViewModelLocator x:Key="Locator"
d:IsDataSource="True" />

我相信 IsDataSource 属性会告诉 Blend 将其放在 DataTab 上......但我并没有为我的 Datamanipulations 使用那么多混合,所以我并不担心它。

关于wpf - 在运行时在 MVVM 中将 WPF ListBox ItemsSource 从 ObservableCollection<T> 切换到 CollectionViewSource,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6088181/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com