簡體   English   中英

WPF C#4.5 ListBox更新非常慢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM