Listview   otázka

VB.NET

Ahoj!

Může mi prosím někdo poradit ohledně filtrování dat v ListView.

Mám tabulku s více sloupci,kde první obsahuje(jmeno_nástroje),podle kterého

následně třídím celou tabulku tak,aby v ní zůstali pouze ta data,která obsahují(jmeno_nastroje)

Protože způsob,kterým to provádím,viz. kod níže se mi zdá dost pomalý.

Existuje jiná možnost,která provede třídění dat rychleji? Je některý z cyklů rychlejší než

ten můj uvedený?

Děkuji

   Dim filtr As String = jmeno_nastroje 'filtrovaný popis nástroje
            For Each item As ListViewItem In ListView1.Items
                If Not item.SubItems(0).Text = filtr Then
                    item.Remove()
                End If
            Next
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zdravím,

žádný závažný výkonnostní problém bych tam neviděl ... nicméně bych data filtroval do zvláštní kolekce z původního datového zdroje (DB, soubor ...) ne přímo v list view. Ono to přeci ani nemůže fungovat, pokud spustíte filtrování dat dvakrát tak z předchozího filtrování jsou některá data již smazána, a přeci relevantní. :-)

Zkusím popsat schématicky (omlouvám se za C#)


// vybrání a vyfiltrování dat ze zdroje
var filteredData = dataSource.GetItems().Where(i => i.jmeno_nastroje == jmeno_nastroje);

// vyčištění list view
ListView1.Items.Clear();

foreach(var item in filteredData)
{
   ListView1.Items.Add(item);
}

Jen pro info, kolik řádově tam těch záznamů máte ? Dal by se zvážit ještě index (např. v dictionary).

R.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ahoj!

Děkuji za odpověď

Ono je to vidět na pomalejším PC(pracovním, navíc ve stroji).

Položek je tam teď cca 200,což není mnoho,ale to zpomalení je tam znát,ne že

by bylo nějak dramatické trvá to asi 2s.Ale pokud by tam bylo těch položek více....??

Ono to takto funguje,protože vždy před filtrováním je načten celý seznam a následně dochází k filtrování.To načtení celého seznamu je bleskové,zásek se koná až u toho filtrování. Kdyby to šlo vysvětlit pokud možno nějak polopatě...C# mi moc neříká.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zdravím,

2s na tak relativně "málo" položek je poměrně hodně. Nevidím důvod proč by to nemělo proběhnout řádově v milisekundách (pokud to není opravdu historický kousek železa :-). Zkus si položky držet v paměti (nebo načíst znovu z datového zdroje), vyfiltrovat (if a ukládat třeba do listu), vyčistit list view (listView.Items.Clear()) a naplnit ho znovu již vyfiltrovanými položkami.

Přiznám se, že nevím co ve uvnitř dělají metody item.SubItems(0) a item.Remove(), takže nemohu zhodnotit režii těchto operací. Nicméně skutečně, pokud by bylo položek více a více, tak by čas vykonání narůstal (pravděpodobně lineárně).

R.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ahoj!

No já nejsem žádný specialista,ale podle mne celý seznam načtu do ListViewu a potom se tam děje asi toto.

item.SubItems(0) přečte první řádek a pokud nesouhlasí s filtem tak řádek vymaže,pokud ano,tak ho tam nechá a pokračuje dále,proto ten zdlouhavý běh(ale je to jen má doměnka,třeba chybná).....

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To ano, jen nevím co ty operaci dělají uvnitř frameworku, zkus postupovat jak jsem uvedl, pokud to nepomůže, zkus uvést víc detailů implementace aplikace, třeba bude problém někde jinde :-).

R.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Myslím,že ten problém nastává až v okamžiku toho filtrování v uvedeném kodu. Protože pokud ho vynechám,tak vše proběhne bleskově(načtení celého seznamu). Zkusím se na to ještě podívat a nějak se s tím poprat,aby to pokud možno filtrovalo někde na pozadí. Děkuji za radu i ochotu.

Doufal jsem v nějaké pro mne jednoduché řešení,ale nevzdávám to....

Martin

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tady je staré vlákno s vyhledáváním a filtrováním, třeba to pomůže :

http://www.dotnetportal.cz/forum/tema/18...

Co se pružnosti týče těžko říct, listview se pokaždé smaže a načte znova

datatable se změněným filtrem, chce to vyzkoušet. Před načítáním to ještě

vylepšit v SetDataSource a přidat před cyklus for Me.BeginUpdate a za něj

Me.EndUpdate.

Případně se inspirovat níže u datagridview a použít BindingSource, pokud

budeš trvat na užití listview, ale datagridview možná poslouží i lépe...

Ještě sčítání sloupců v listview od stejného autora jako filtrování :

http://www.dotnetportal.cz/forum/tema/15...

Filtrování pomocí BindingSource.Filter a DataGridView :

https://msdn.microsoft.com/en-us/library...

Datagridview updated sample ke stažení, snad to ještě funguje :

https://blogs.msdn.microsoft.com/winform...

Vše nalezeno pomocí hledání zde na webu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ahoj!

Děkuji za odkazy,projedu to,jen jestli to na mě už nebude trochu komplikovanější.

Martin

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den. Nedávno jsem podobnej problém řešil. Teprve s programováním začínám tak jsem nevymýšlel žádný složitosti a vytvořil si dva listview u jednoho jsem nastavil hodnotu visible na false a nahrál do něho všechny položky do druhého jsem položky přidával až filtrováním. Jo a vypadá to, že rychlejší je položku editovat než vytvářet a mazat, tak další filtrování jsem psal tak aby se položky přepisovali...když nějaká zbyla tak jí vymažu, když chybí tak vytvoři.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ahoj!

Děkuji za inspiraci.Asi by se dalo jít event. i tímto směrem

M.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

a nepomohl by aspon listview1.beginupdate a listview1.endupdate?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ahoj!

Děkuji,tohle vypadá opravdu hóóódně nadějně....!

Nemám teď možnost to vyzkoušet na pomalém počítači ve stroji,ale i na běžném PC je nárůst zrychlení

opravdu rapidně znát a jak jednoduše,jen je třeba znát ty cestičky!

Ještě jednou děkuji

Martin

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Příklad filtrování

Public Class Form1
 
    Dim lv As DataListView, dt As DataTable
    Dim tb As TextBox, cb As ComboBox
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        lv = New DataListView
        tb = New TextBox
        cb = New ComboBox
        cb.DropDownStyle = ComboBoxStyle.DropDown
        Dim pnl As Panel = New Panel
        With pnl
            .Controls.Add(cb)
            .Controls.Add(tb)
            tb.Left = cb.Width
            .Height = tb.Height
        End With
 
        Me.Controls.Add(lv)
        lv.Location = New System.Drawing.Point(0, pnl.Height)
        lv.Dock = DockStyle.Fill
        Me.Controls.Add(pnl)
        pnl.Dock = DockStyle.Top
        AddHandler cb.SelectedIndexChanged, New EventHandler(AddressOf cb_SelectedIndexChanged)
        AddHandler tb.TextChanged, New EventHandler(AddressOf tb_TextChanged)
 
        dt = New DataTable
        dt.Columns.Add("Jméno")
        dt.Columns.Add("Příjmení")
 
        dt.Rows.Add("Honza", "Dufek")
        dt.Rows.Add("Pavel", "Dufek")
        dt.Rows.Add("Jan", "Hlávka")
        dt.Rows.Add("Milan", "Dufek")
        dt.Rows.Add("Jan", "Duffon")
        dt.Rows.Add("Pavel", "Hlávka")
        dt.Rows.Add("Ondřej", "Linhart")
        dt.Rows.Add("Mirek", "Linhart")
 
        lv.SetDataSource(dt)
 
        For Each c As DataColumn In dt.Columns
            lv.Columns.Add(c.Caption)
            cb.Items.Add(New String(c.Caption))
        Next
 
        cb.SelectedIndex = 0
    End Sub
 
    Private Sub cb_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
        tb.Clear()
    End Sub
 
    Private Sub tb_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
        If tb.Text = vbNullString Then
            lv.SetDataSource(dt)
        Else
            Dim tbFilter As New DataTable
            tbFilter = dt.Clone
            Dim flt As String
            flt = cb.Text & " Like '" & tb.Text & "%'"
            Dim dr() As DataRow = dt.Select(flt)
            For i As Integer = 0 To dr.Length - 1
                tbFilter.ImportRow(dr(i))
            Next
            lv.SetDataSource(tbFilter)
        End If
    End Sub
End Class
 
Public Class DataListView
    Inherits ListView
 
    Public Sub SetDataSource(ByVal fromDataTable As DataTable)
        Me.Items.Clear()
 
        For i As Integer = 0 To fromDataTable.Rows.Count - 1
            Dim lvItem As ListViewItem
            lvItem = Me.Items.Add(fromDataTable.Rows(i).Item(0).ToString)
            For j As Integer = 1 To fromDataTable.Columns.Count - 1
                lvItem.SubItems.Add(fromDataTable.Rows(i).Item(j).ToString)
            Next j
        Next i
 
    End Sub
 
    Public Sub New()
        Me.View = Windows.Forms.View.Details
        Me.HideSelection = False
        Me.GridLines = True
    End Sub
End Class
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Děkuji všem za nápady a podněty.

Pužil jsem cyklus viz. můj první příspěvek a k tomu pouze dodal

listview1.beginupdate a listview1.endupdate a funguje to naprosto

skvěle i na pomalém PC.Odezva je víceméně okamžitá.

Ještě jednou děkuji

M.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback