我刚开始使用Redis,我正在将它用于我的一个个人项目。
包含大约10k个对象public Class FileList
{
public string FileName { get; set;}
public string FolderName { get; set;}
}
我最初在加载时在ListBox ResultsView
中显示此列表。我有TextBox
我可以在其中输入字符,在TextBoxChanged_Event
我正在调用一个函数,该函数将向RedisDB查询包含我在{中输入的字符的所有FileList
个对象{1}}并将其存储在TextBox
中,该ResultsList<FileList>
将在foreach
中循环播放,然后添加到ListBox
。
开始显示结果至少需要一秒钟,而且速度不是很快。
现在,如果我对MasterList<FileList>
执行相同的查询,那么它会更快但仍然不够快。
昨天,我尝试使用RavenDb,这需要花费很长时间才能完成相同的任务。
我是否正在Items
将ListBox
添加到forach
ItemSource
这需要花费很多时间,或者是否有任何可以加快速度的ItemList should be empty before binding
{ {1}}我试过但却给了我ResultsView.Items.Clear();
var redisClient = new RedisClient("localhost");
using (var client = redisClient.As<FileList>())
{
var foldersFromRedis = client.GetAll().Where(fileList => fileList.FileName.Contains(this.Search.Text.ToLower()));
foreach (FileList fileList in foldersFromRedis)
{
var listViewItem = new ListViewItem { Content = fileList.FileName , Tag = fileList.FolderName };
this.ResultsView.Items.Add(listViewItem);
}
}
//this.ResultsView.ItemsSource = ResultsFileList;
我确实尝试过几乎类似问题的大多数答案,但没有人帮助过我。
代码
<ListBox Height="374" ScrollViewer.VerticalScrollBarVisibility="Disabled" HorizontalAlignment="Left" Margin="10,0,0,0" Name="ResultsView" VerticalAlignment="Bottom" Width="405" BorderThickness="0" SelectionChanged="MovieNameSelectionChanged" FontFamily="Nobile" FontSize="13" Background="#A6FCFCFC" Foreground="Black" FontStretch="Normal">
<GridView>
<GridViewColumn Header="FileName" DisplayMemberBinding="{Binding FileName}"/>
</GridView>
</ListBox>
private void ApplyViewCollectionSource()
{
_viewSource.Filter += ViewSourceFilter;
_viewSource.Source = _fileList = (List<FileList>)PopulateFileListEnglishWithReturn();
ResultsView.ItemsSource = _viewSource.View;
_timer.Interval = new TimeSpan(0, 0, 0, 0, 200);
_timer.Tick += (o, e) =>
{
_timer.Stop();
_viewSource.View.Refresh();
};
Search.TextChanged += (o, e) => _timer.Start();
}
更新1:
添加了ViewCollectionSource,如下所示
private void ViewSourceFilter(object sender, FilterEventArgs e)
{
var src = e.Item as FileList;
e.Accepted = src != null;
if (string.IsNullOrEmpty(Search.Text)) return;
var regex = new Regex(Search.Text, RegexOptions.IgnoreCase);
e.Accepted = regex.IsMatch(src.FileName);
}
在构造函数中调用。过滤器如下:
ListBox
这适用于我的要求,但仅限于TextBox中的第3个字符。键入第一个字符后,_fileList
需要2秒才能更新,第二个字符需要1秒。在此之后,它几乎是瞬间。主列表{{1}}中有大约5000个项目。
在前2个字符搜索过程中提高速度的方法有哪些?
答案 0 :(得分:0)
每次要过滤时都不要重新加载数据。 WPF具有过滤现有数据的机制,而无需往返服务器。考虑使用CollectionView为您进行过滤。集合视图允许您更改呈现给用户的内容,而无需触及数据本身。
答案 1 :(得分:0)
首先,我个人不喜欢空绑定...我给Window / UserControl一个名字
<Window ...
Name="your_name_here">
然后在绑定中,绑定到后面的代码上的属性(假设它被称为property_for_binding
),你将它绑定它:
<Listbox ...
ItemSource={Binding ElementName=your_name_here , Path=property_for_binding} />
话虽如此,我确实更喜欢MVVM方法,但没关系,重新开始工作...... 您是否尝试在功能上添加一些秒表?您可以在调用DB之前打印到控制台,在调用DB(排除它是您的数据库错误)之后,然后在排序之前/之后打印,依此类推。通过这种方式,您可以看到最慢的因素。
正如评论所说,你可能不应该在数据库中查询文本框中的每个更改(假设您在文本更改时执行此操作,而不是在完成输入后通过按钮),因为通常您的数据库将给出相同的结果页面内的所有搜索(除非它从其他地方进行了大量修改,在这种情况下,我猜你没有其他选择)。
因此,缓存结果一次,搜索该变量,并用结果填充您要绑定的属性。
修改强>
你总是可以在用户输入3个字符之后运行搜索,解决问题(假设有10K项,一个字母无关紧要,他会继续搜索)。
其他选项是仅在上次击键后经过一段时间后才进行搜索。
最后但并非最不重要的是,这里有一个可能有用的链接(解决你在列表中添加项目的第一个循环):Why is AddRange faster than using a foreach loop?
答案 2 :(得分:0)
我发现ListBox这类问题很常见,您是否检查过以确保数据虚拟化未被禁用且VirtualizationMode设置为“回收”?
我发现另一件有用的事情是使用DispatchTimer在输入最后一个字符后的几秒钟内触发搜索。大多数用户不介意在结束时进行短暂的等待,但他们不希望GUI在打字时感到迟钝。