成人欧美一区二区三区的电影,日韩一级一欧美一级国产,国产成人国拍亚洲精品,无码人妻精品一区二区三区毛片,伊人久久无码大香线蕉综合

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

Winform版本與avalonia開發(fā)差異比較:列表虛擬化的實現(xiàn)-百萬數(shù)據(jù)輕松展示

freeflydom
2025年10月11日 17:9 本文熱度 913

一、列表虛擬化與海量數(shù)據(jù)展示

tds?中,當(dāng)用戶在關(guān)鍵詞后加了/a參數(shù),會列出所有的文件。此時可能會有上百萬個。為了流暢操作和顯示這些數(shù)據(jù),只能借助列表虛擬化技術(shù)來實現(xiàn)。

列表虛擬化是一種優(yōu)化技術(shù),用于處理大量數(shù)據(jù)時提高性能和用戶體驗。它通過實時計算來模擬海量數(shù)據(jù)的展示,此時的性能流暢度與數(shù)據(jù)大小無關(guān),僅與實時計算需要的執(zhí)行時間有關(guān)。其核心思想是按需加載和按需渲染。
在用戶滾動列表時,虛擬化技術(shù)會自動將大量數(shù)據(jù)分成多個小塊(或頁面),每次只加載和渲染當(dāng)前視圖范圍內(nèi)的數(shù)據(jù)塊。這個過程是事件驅(qū)動,當(dāng)用戶滾動列表時,這些事件通知應(yīng)用程序加載和渲染新的數(shù)據(jù)塊。在后臺,虛擬化管理模塊還將即將進(jìn)入視圖范圍的數(shù)據(jù)項緩存起來,以便快速訪問。這減少了對數(shù)據(jù)源的頻繁訪問,提高了性能。

主要原理很簡單:

  • 視口渲染:列表虛擬化技術(shù)的核心是只渲染用戶當(dāng)前可視區(qū)域內(nèi)的元素,而不是一次性渲染整個列表。當(dāng)用戶滾動時,動態(tài)地加載和卸載元素。
  • 占位元素:為了保持列表的滾動條高度和布局正確,虛擬化列表會使用占位元素來表示未渲染部分的高度。
  • 元素復(fù)用:虛擬化列表通常會重用相同的組件實例(數(shù)據(jù)或UI元素)來渲染不同的數(shù)據(jù)項,通過緩存從而減少開銷。

Winform和Avalonia各自的列表虛擬化技術(shù)實現(xiàn)不太一樣,Winform需要考慮對實時事件手動處理,Avalonia則可以依賴自帶的響應(yīng)式模式綁定自動完成。我一起來看看具體都實現(xiàn)吧。

二、Winform 與 Avalonia 實現(xiàn)的對比

2.1 Winform虛擬列表,以ListView為例

Winform的虛擬列表的開啟需要將控件ListViewVirtualMode屬性設(shè)置為true。在虛擬化過程中,用戶滾動列表時,ListView會觸發(fā)兩個關(guān)鍵事件,需要我們進(jìn)行實現(xiàn):

  • ListView.CacheVirtualItems事件:當(dāng)用戶滾動列表時,此事件會被觸發(fā)。它通知我們哪些項即將進(jìn)入視圖范圍,我們可以在這個事件中緩存這些項。例如,可以使用一個數(shù)組來存儲這些即將顯示的項,作為我們的cache。這樣可以減少對數(shù)據(jù)源的頻繁訪問,提高性能。
  • ListView.RetrieveVirtualItem事件:當(dāng)ListView需要將某個項渲染到UI上時,會觸發(fā)此事件。我們可以通過從緩存中讀取對應(yīng)的項并返回給UI來實現(xiàn)。如果緩存中沒有找到對應(yīng)的項,我們也可以選擇動態(tài)生成它。
    CacheVirtualItems有時候也可以不實現(xiàn),RetrieveVirtualItem也可以實時處理動態(tài)生成ListViewItem。

以下是簡化后的代碼實現(xiàn),需要詳細(xì)實現(xiàn)朋友們可以參考項目源碼。

private ListViewItem[] CurrentCacheItemsSource; // 用于存放緩存的數(shù)組
private int firstitem; // 緩存的起始索引
private bool refcache = false; // 標(biāo)記是否需要重新緩存
// 動態(tài)獲取對象并提供給UI
private void ListView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
    // 如果緩存中有對應(yīng)的項,直接從緩存中獲取
    if (CurrentCacheItemsSource != null && e.ItemIndex >= firstitem && e.ItemIndex < firstitem + CurrentCacheItemsSource.Length)
    {
        e.Item = CurrentCacheItemsSource[e.ItemIndex - firstitem];
    }
    else
    {
        // 如果緩存中沒有對應(yīng)的項,動態(tài)生成一個
        e.Item = GenerateListViewItem(e.ItemIndex);
    }
    // 如果動態(tài)生成失敗,返回一個空對象以避免異常
    if (e.Item == null)
    {
        e.Item = new ListViewItem(new string[] { "加載失敗", "", "" });
    }
}
// 生成緩存
private void ListView1_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e)
{
    // 如果要緩存的范圍已經(jīng)在緩存中,直接返回
    if (e.StartIndex >= firstitem && e.EndIndex <= firstitem + CurrentCacheItemsSource.Length)
    {
        return;
    }
    // 更新緩存的起始索引和長度
    firstitem = e.StartIndex;
    int length = e.EndIndex - e.StartIndex + 1;
    // 重新生成緩存
    CurrentCacheItemsSource = new ListViewItem[length];
    for (int i = 0; i < length; i++)
    {
        // 從數(shù)據(jù)源中獲取對應(yīng)的項并存入緩存
        CurrentCacheItemsSource[i] = GenerateListViewItem(firstitem + i);
    }
    // 標(biāo)記緩存已更新
    refcache = false;
    // 自動調(diào)整列寬以適應(yīng)內(nèi)容
    ListView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
}
// 根據(jù)索引生成ListViewItem
private ListViewItem GenerateListViewItem(int index)
{
    // 這里可以根據(jù)實際的數(shù)據(jù)源來生成ListViewItem
    // 示例:從一個列表中獲取數(shù)據(jù)
    if (index < vresultNum)
    {
        FrnFileOrigin f = vlist[index];
        return new ListViewItem(new string[] { f.Name, f.Path, f.Size.ToString() });
    }
    return null;
}

實際使用中,ListViewItem虛擬化的緩存是我們手動將數(shù)據(jù)關(guān)聯(lián)到一個數(shù)組或List中的。當(dāng)數(shù)據(jù)發(fā)生變化時,除了自動刷新各個索引處對象的值外,還需要控制長度。
如果說緩存有100個元素,我們可以通過設(shè)定ListView的VirtualListSize屬性來改變要顯示的元素個數(shù),比如只顯示前10個,這樣就可以在數(shù)據(jù)變小的時避免重新創(chuàng)建數(shù)組/列表對象。

5.2 Avalonia的虛擬面板 以為例

與Winform不同,Avalonia的ListBox等控件中沒有VirtualMode屬性,需要通過VirtualizingStackPanel等方式開啟,xml代碼如下。

<ListBox x:Name="fileListBox" ItemsSource="{Binding Items.DisplayedData, Mode=OneWay}" >
				
				<ListBox.ItemsPanel>
					<ItemsPanelTemplate>
						<VirtualizingStackPanel />    <!-- 虛擬化面板 -->
					</ItemsPanelTemplate>
				</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
							<DataTemplate>
            <!-- 自定義實現(xiàn) -->
              </DataTemplate>
				</ListBox.ItemTemplate>
</ListBox>

綁定的核心思想是,我們將真實數(shù)據(jù)的引用存起來,Listbox則是綁定到一個IEnumerable<T>對象接口中。當(dāng)真實數(shù)據(jù)需要更新時,我們控制IEnumerable<T>的更新。
由于IEnumerable<T>是延遲實現(xiàn)的(yield return)因此不會產(chǎn)生額外數(shù)組開銷??梢酝ㄟ^Take(DisplayCount)的方法去動態(tài)控制所展示數(shù)據(jù)的長度,類似于WinformVirtualListSize, 這樣能夠有效提升性能,尤其是在處理大量數(shù)據(jù)以及處理數(shù)據(jù)長度頻繁變化的場景。

在下面的代碼中給出了一個ViewModel的示例實現(xiàn),需要用到Avalonia.ReactiveUI庫(這個庫需要單獨在Nuget上下載)。

public class DataViewModel : ReactiveObject
{
    private IList<FrnFileOrigin> _allData = [];
    private IEnumerable<FrnFileOrigin> _displayedData = [];
    private int _displayCount = 100;
    public IEnumerable<FrnFileOrigin> DisplayedData
    {
        get => _displayedData;
        private set => this.RaiseAndSetIfChanged(ref _displayedData, value);
    }
    bool isShowOpenWith = true;
    public bool IsShowOpenWith
    {
        get => isShowOpenWith;
        set
        {
             this.RaiseAndSetIfChanged(ref isShowOpenWith, value);
        }
    }
    public int DisplayCount
    {
        get => _displayCount;
        private set
        {
            _displayCount = value;
        }
    }
    public DataViewModel()
    {
    }
    public void Bind(IList<FrnFileOrigin> _allData)
    {
        if (this._allData != _allData)
        {
            // 生成測試數(shù)據(jù)(實際中可能從文件或數(shù)據(jù)庫加載)
            this._allData = _allData;
            //UpdateDisplayedData();
        }
    }
    public void UpdateDisplayedData()
    {
        // 使用 LINQ 的 Take(),這是惰性求值的,性能很好
        DisplayedData = _allData.Take(DisplayCount);
    }
    // 快速切換到不同數(shù)量級
    public void SetDisplayCount(int count)
    {
        DisplayCount = count;
    }
}

在上述代碼中,DisplayedData 屬性通過 RaiseAndSetIfChanged 方法來實現(xiàn)屬性值的更新和通知,確保綁定到該屬性的界面元素能夠及時響應(yīng)數(shù)據(jù)的變化。而 DisplayCount 屬性在更新時會調(diào)用 UpdateDisplayedData() 方法,從而保證 DisplayedData 的內(nèi)容始終與 DisplayCount 保持一致。

還有一個問題就是,Avalonia在VirtualizingStackPanel中,虛擬化后可能數(shù)據(jù)不是瓶頸,UI顯示同樣會造成卡頓,尤其是在應(yīng)用虛擬化時實時渲染發(fā)復(fù)雜的布局。因此我們可以設(shè)置VirtualizingStackPanel.CacheLength屬性。
這個屬性是一個double值,決定了在視口上方和下方(或左方和右方)要保持多少額外的空間。值為 0.5 表示系統(tǒng)在每一側(cè)(上下或左右)將緩沖視口大小的一半,此時將實例化更多UI元素。盡管會占更多內(nèi)存,但大大減少Measure-Arrange循環(huán)的次數(shù)(measure:確定控件所需的最小寬度和高度; arrange:將控件放置在父控件中,并確定其最終的位置和大小;Arrange:) 否則,在UI復(fù)雜程度較高時,GC壓力巨大。

三、最后

感謝您的耐心閱讀,希望各位從零開始的新朋友和老朋友有所收獲!如果你對這篇文章的內(nèi)容有任何建議或想法,歡迎隨時交流!本文中TDS文件搜索工具的Winform版本已在倉庫完全開源了!點個 Star ??支持一下!代碼倉庫地址 https://github.com/LdotJdot/TDS_Winform

轉(zhuǎn)自https://www.cnblogs.com/luojin765/p/19118610


該文章在 2025/10/11 17:09:24 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved