[英]WPF C# 4.5 ListBox Update Very Slow
我剛剛開始使用Redis,並將其用於我的個人項目之一。 Redis數據庫包含約1萬個對象
public Class FileList
{
public string FileName { get; set;}
public string FolderName { get; set;}
}
我最初在加載時在ListBox ResultsView
顯示此列表。 我有一個TextBox
,可以在其中輸入字符,並且在TextBoxChanged_Event
上,我正在調用一個函數,該函數將查詢RedisDB中包含我在TextBox
鍵入的字符的所有FileList
對象,並將其存儲在ResultsList<FileList>
中在foreach
循環,然后添加到ListBox
。
開始顯示結果至少需要一秒鍾,而且速度不是很快。
現在,如果我在MasterList<FileList>
上執行相同的查詢,那么它會快一些,但仍然不夠快。
昨天,我嘗試了RavenDb,它花了很長時間才能完成相同的任務。
是我在花費大量時間的forach
中將Items
添加到ListBox
forach
,還是有什么可以加快它速度的事情,例如我嘗試過的ItemSource
,但給我的錯誤是ItemList should be empty before binding
我確實嘗試了幾乎所有類似問題的大多數答案,但沒有一個幫助我。
碼
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>
更新1:
添加了如下的ViewCollectionSource
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();
}
在構造函數中被調用。 過濾器如下:
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);
}
這非常適合我的要求,但僅在TextBox中的第三個字符之后。 鍵入第一個字符后, ListBox
需要2秒鍾才能更新,第二個字符需要1秒。 此后,它幾乎是瞬間。 主列表_fileList
中大約有5000個項目。
有什么方法可以提高前2個字符搜索的速度嗎?
不要在每次要過濾時重新加載數據。 WPF具有適當的機制,可以過濾現有數據而無需往返服務器。 考慮使用CollectionView為您進行過濾。 集合視圖使您可以更改呈現給用戶的內容,而無需接觸數據本身。
您可以在這里找到一個有效的示例: http : //social.msdn.microsoft.com/Forums/vstudio/en-US/0d2b882d-cf56-4385-9b76-dd280c4c35b1/filter-a-readonlycollection-for-binding-a-列表視圖?論壇= WPF#213dda80-5d29-47fa-B832-ea7e098590d7
首先,我個人不喜歡空綁定...我要給Window / UserControl命名
<Window ...
Name="your_name_here">
然后在綁定中,綁定到后面代碼的屬性(假設它稱為property_for_binding
),則將其綁定為:
<Listbox ...
ItemSource={Binding ElementName=your_name_here , Path=property_for_binding} />
話雖這么說,我確實更喜歡MVVM方法,但是請不要介意重新投入使用...您是否嘗試在功能上使用一些秒表? 您可以僅在調用DB之前,調用DB之后(排除您的DB故障),然后在排序之前/之后打印到控制台。 這樣,您可以看到最慢的因素。
就像評論所說,您可能不應該查詢數據庫中文本框的每個更改(假設您是在文本更改時執行此操作,並且鍵入完成后不通過按鈕進行查詢),因為通常您的數據庫將為數據庫中的所有搜索提供相同的結果頁面(除非正在其他地方進行大量修改,在這種情況下,我想您沒有其他選擇)。
因此,將結果緩存一次,搜索該變量,然后用結果填充將要綁定到的屬性。
編輯:
您始終只能在用戶輸入3個字符后才能運行搜索,從而解決了該問題(假設有1萬個項目,一個字母也無濟於事,他將繼續搜索)。
其他選擇是僅在自上次擊鍵起經過一段時間后進行搜索。
最后但並非最不重要的一點是,這里的鏈接也可能有幫助(解決了將項目添加到列表的第一個循環): 為什么AddRange比使用foreach循環更快?
這些問題在我發現的ListBox中很常見,您是否檢查過以確保未禁用數據虛擬化並且VirtualizationMode設置為“ Recycling”?
我發現有幫助的另一件事是,使用DispatchTimer在鍵入最后一個字符幾秒鍾后觸發搜索。 大多數用戶不介意最后等待一小段時間,但是他們不希望在鍵入時GUI感覺遲鈍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.