datagridview virtuele modus, update RowCount zorgt ervoor dat CellValueNeeded voor alle rijen vuurt

Ik probeer de virtuele modus van datagridview te implementeren, maar als ik RowCount op een nummer instel (om de schuifbalk weer te geven), wil het raster alle rijen tegelijk hebben, niet alleen het weergegeven.

DataGridView grid = new ...;

grid.VirtualMode = true;
grid.CellValueNeeded += OnCellValueNeeded;
grid.RowCount = dataprovider.GetFullCount();

Hoe kan ik het raster vertellen om alleen de weergegeven rijen aan te vragen?

4

5 antwoord

Dit is slechts een schatting, maar heeft u de waarden AutoSizeRowsMode of AutoSizeColumnsMode ingesteld op AllCells of zijn er ook kolommen op ingesteld? Probeer de modus voor het wijzigen van de grootte in te stellen op Geen of alleen DisplayedCells en kijk of er nog steeds een probleem is.

4
toegevoegd
Dit heeft me geholpen. Dank je!
toegevoegd de auteur tareqx3, de bron
helaas raster.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; en grid.Columns.ForEach (col => col.AutoSizeMode = DataGridViewAutoSizeColumnMode.None) veranderen dit gedrag niet
toegevoegd de auteur Firo, de bron

Ik weet niet zeker of dit hetzelfde probleem is als ik had, maar ik kreeg wel erg slechte prestaties als ik regelmatig de RowCount op een VirtualMode DataGridView drastisch veranderde.

Wat me opviel was dat de schuifbalk "langzaam" veranderde; dat wil zeggen dat het eruit zag alsof het mijn virtuele rijen (!) afzonderlijk verwijderde.

In elk geval doet een raster.Rows.Clear() vóór elke oproep naar raster.RowCount = n de prestaties drastisch verbeteren.

2
toegevoegd
Dat is geen antwoord op de oorspronkelijke vraag maar lost mijn prestatieprobleem op. Bedankt!
toegevoegd de auteur Kuba, de bron
mijn probleem is dat grid.RowCount = n onmiddellijk OnCellValueNeeded voor alle rijen zou roepen, zelfs niet getoond
toegevoegd de auteur Firo, de bron
Ik zie ook hetzelfde probleem. Ik gebruik de oplossing RowCount = 0 omdat het instellen van RowCount 10 keer of langer duurt zonder dat dit gebeurt wanneer u van b.v. RowCount = 10000 tot RowCount = 2 , maar houd er rekening mee dat bij gebruik van deze oplossing ook de selectie handmatig moet worden hersteld. Ik zou willen dat de netfx geen lus gebruikte in RowCount.set() voor waarde! = 0 ...
toegevoegd de auteur binki, de bron

Ik heb hetzelfde probleem en ik heb de oplossing geprobeerd om een ​​actieve vlag in te stellen zoals jij, en ik heb ook de oplossing geprobeerd om RowCount in te stellen op 0 (of grid.Rows.Clear ()) voordat je de nieuwe RowCount instelt.

Beide dingen verbeterden de prestaties, maar geen van beide versnelde genoeg om zo direct mogelijk te zijn als ik wil, omdat ik het raster dynamisch in realtime filter op basis van input van een zoekvak.

Ik vond twee andere oplossingen:

1) Gebruik paginering zodat u de RowCount niet zo hoog hoeft in te stellen om mee te beginnen. Ik denk dat dit een geweldige oplossing is als je al gebruikmaakt van paginering (in welk geval je hier niet zou zijn) maar een te omslachtige als je niet van plan was om het te implementeren.

2) Plaats de aanroep om de RowCount in een eigen thread in te stellen. Dit is degene die ik ga proberen. Eerlijk gezegd weet ik niet zeker hoe veilig deze is als je cellen probeert te bewerken terwijl de draad nog steeds aan het eindigen is, maar ik denk dat ik het snel genoeg te weten zal komen.

BEWERK:

OK, dus ik heb geprobeerd het in te rijgen in de hoop dat het zou lukken, aangezien ik elders las dat het echt een andere man hielp. Het lijkt een goede oplossing te zijn ALS je gaat de waarde af en toe veranderen, maar het hangt nog steeds als je het meerdere keren achter elkaar doet (wat ik ben). Ik denk dat dit komt omdat je Invoke() moet gebruiken en de tweede keer dat het nog steeds wacht tot de eerste is voltooid. Ik kan niet zeggen dat ik volledig begrijp wat de deal is, maar ik heb besloten om nu gewoon met de lege rijen te leven omdat het ZOO veel sneller en minder complex is als ik ze daar gewoon achterlaat.

0
toegevoegd
@Firo Ja. Ik vind het gewoon ontzettend stom dat wanneer je het recordtelling verlaagt, het feitelijk nog probeert waarden voor records te krijgen boven de telling die je hebt ingesteld voordat het voltooien van de telling is voltooid. En wat meer is, waarom probeert het zelfs om waarden te krijgen voor records die niet eens op het scherm worden weergegeven? Ik denk nog steeds dat de DGV een van de grootste en meest geweldige besturingselementen is die Microsoft ons heeft geboden, maar ze hadden dat deel zeker een beetje beter kunnen doen.
toegevoegd de auteur BVernon, de bron
er is altijd een vertraging tussen het aanvragen van de gegevens en het ontvangen van de gegevens. Responsieve gebruikersinterface met tijdelijk lege cellen is de beste UX die ik me kan voorstellen, want als de gevraagde gegevens niet echt de gegevens zijn die de gebruiker wil hebben (hij scrolt bijvoorbeeld), maakt het niet uit
toegevoegd de auteur Firo, de bron

helaas lijkt dit het standaardgedrag te zijn. ik zou het ook kunnen oplossen

void OnCellValueNeeded(...)
{
    if(!_active) return;
}

grid.VirtualMode = true;
grid.CellValueNeeded += OnCellValueNeeded;
_active = false;
grid.RowCount = dataprovider.GetFullCount();
_active = true;

of het implementeren van IBindingList, ITypedList met complexe lui ophalen in achtergrondthread

Update: the problem seems to be fixed now. I can not reproduce it anymore using the following:

static class Program
{
    private static Form form;
    private static int i;

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        var grid = new DataGridView
        {
            Dock = DockStyle.Fill,
            VirtualMode = true,
            AllowUserToAddRows = false,
            Columns =
            {
                new DataGridViewTextBoxColumn { HeaderText = "foo" },
                new DataGridViewTextBoxColumn { HeaderText = "bar" },
            },
        };
        grid.CellValueNeeded += OnCellValueNeeded;
        form = new Form
        {
            Controls = { grid }
        };

        //grid.RowCount = 0;
        grid.RowCount = 10000;

        Application.Run(form);
    }

    private static void OnCellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
    {
        i++;
        form.Text = i.ToString();
        e.Value = "fooValue";
    }
}
0
toegevoegd
Zorg ervoor dat de kolom autosize-modus niet is ingesteld op alle cellen
toegevoegd de auteur Marcin, de bron
heeft geen verschil gemaakt, zie mijn reactie op stackoverflow.com/a/8404739/671619
toegevoegd de auteur Firo, de bron
@VisakhVA wat werkt niet: mijn oplossing of dat het niet magisch is opgelost op uw computer?
toegevoegd de auteur Firo, de bron
Het zal niet werken en hetzelfde gedrag vertonen
toegevoegd de auteur Visakh V A, de bron

U moet de RowCount op nul zetten voordat u het volledige aantal kunt instellen.

DataGridView grid = new ...;
grid.VirtualMode = true;
grid.CellValueNeeded += OnCellValueNeeded;
grid.RowCount = 0;
grid.RowCount = dataprovider.GetFullCount();
0
toegevoegd
mijn probleem is dat grid.RowCount = dataprovider.GetFullCount() onmiddellijk OnCellValueNeeded voor alle rijen zou roepen, zelfs niet getoond. Stel RowCount in op 1000 met één kolom en gebruik Thread.Sleep (100); e.Value = "Something;" in OnCellValueNeeded .
toegevoegd de auteur Firo, de bron
Dit lijkt overeen te komen met de suggestie van social.msdn.microsoft.com/Forums/windows/en-US/&ellicle; . Maar niemand zegt waarom dit anders zou moeten werken. .Netfx is eigenzinnig?
toegevoegd de auteur binki, de bron
Het instellen van RowCount op nul voordat een andere telling wordt ingesteld, voorkomt dat OnCellValueNeeded alle rijen oproept. Probeer het gewoon, het werkt voor mij.
toegevoegd de auteur Cem Mutlu, de bron