I am trying to improve the performance on my winforms project, and I wanted to use the same idea as I did in the Delphi projects many years ago.
I remember that in Delphi the gridView had a DataControler property and it had an option so set GridMode = true
This made the loading of the grid already somewhat better, but it disabled the sorting and the filtering.
The filtering could be enable again by some property AutoFilter or something ,and the sorting could be done by manipulating the order by of the query.
But in winforms I cannot find a DataController property. I looked everywhere (I think) but I cannot find the DataController, nor the GridMode property or the AutoFilter property.
How does one do this in the winforms gridview ?
Hello Guido,
Would you please describe the performance issue in greater detail? Usually, Grid works fast enough with up to one million records. If the amount of data is greater, we recommend using Server Mode (Large Data Sources: Server and Instant Feedback Modes) or Virtual Source (Infinite Scrolling).
If you are looking for a way to implement pagination in Grid, refer to the following article: Grid Control - How to implement the pagination functionality.
See also:
DevExpress WinForms Troubleshooting - Performance Issues
Well I noticed the problem when I open large tables using a tool I have build with Delphi.
In this tool opening a table with about 340000 rows it opens instantly, which is normal because that are not that much rows.
When opening with a winforms application using your grid it takes about 1 or 2 seconds
Since your grid offers much usefull stuff, I decided to try your grid in the delphi tool also, and the performance there also degraded horrible. Luckily there is a GridMode in the Delphi version that makes the performance acceptable, without devexpress controls it is still faster even when loading the entire table…
Anyway, since my application has lots of forms that have 5 or more detail tables on them, I wanted to improve the performance by using the GridMode, but to my surprise there is no GridMode in the winforms version.
So I wanted to know how to do this in winforms, without complicated code that needs to know about bindings. Lots of my forms can have different ResultSet's in the datagridview based on the choices made by the user. So I cannot always do binding to tables and columns in designtime.
That is why a GridMode property seemed like the solution to me, but alas…
I tried the demo center and clicked on open solution, but unfortunate the solution has tons of code not related to the actual demo and I do not have the time to spit that out.
Hello Guido,
Would you please share a small sample project that illustrates the issue?
Is this correct that you used WinForms Grid in the Delphi tool? Or do you obtain an issue with the Delphi Grid?
You are right, WinForms Grid doesn't have such a property. As I mentioned, you need to use Server Mode to load data by portions: Large Data Sources: Server and Instant Feedback Modes.
From what I gather, using a separate server mode data source is not suitable in your scenario. In this case, consider using VirtualServerModeSource. Check the code of the "C:\Users\Public\Documents\DevExpress Demos 19.1\Components\WinForms\CS\GridMainDemo\ServerMode\VirtualServerMode.cs" file to see how to use it.
Or, use the approach described in the following example: Grid Control - How to implement the pagination functionality using SQL queries. The idea of this approach is to use the standard SqlDataAdapter to populate a table based on an SQL command and show data form this table in the Grid.
I look forward to your results.
Hello,
No I am not using the winforms grid in the Delphi tool.
The Delphi tool is for another client which luckily uses Delphi in stead of VS and there I have access to the VCL controls. That is where I decided to try out the Delphi Grid but the performance is not so good compared to the standard Delphi DBGrid. Using the GridMode makes the performance acceptable again.
Why is it that in Delphi it is so easy by using a simple property GridMode and in VS it is complicated again with lots of code ?
Are there any plans to make a GridMode property in the winforms GridControl ?
Hello Guido,
Thank you for the clarification. I created a small sample project with our Grid Control and show 400.000 records in it. As you can see in the attached video and project, loading data takes more time, however, showing data in the Grid is fast. The Grid also works fast when I scroll it. In fact, WinForms Grid loads and paints only visible rows. When the GridMode property is enabled, the VCL Grid works in a similar manner - it loads and paints a fixed number of records from the data set. Taking this into account, it's difficult to determine why WinForms Grid works slowly. I can only assume that loading data takes time in your case. Would you please check it? The simplest way to do it is to use the Stopwatch object to measure data loading time. You can see how you can do it in the attached sample project. Or, modify the attached project in order to illustrate the issue. It will help us find the most suitable solution.
We don't have immediate plans to support this property. If the current approach doesn't help, I suggest that you consider using the PLinqServerModeSource data source. It loads data by portions from the underlying data source stored in memory.
I hope to hear from you soon.
Hello, I will take a look at your sample project.
As for your question about checking if the loading of the data takes time, well let me explain to you what I have noticed.
The code has not changed, the way the data is loaded has not changed, the only thing that changed is the grid control.
So I am actually sure that the loading is not the problem here.
OK the time it needs to fill is still acceptable, but the difference is notible.
And with Forms that have more than one GridControl the little difference becomes greater off course.
A simple property like GridMode would be easy because my application comes close to 50 forms (only counting the forms with gridviews in it)
Hello again,
I have modified the sample project some more, it loads the data once,
and has 3 methods to populate the gridview
From my test it seems that pLinqServerModeSource is slower than just using the database as datasource.
When I use pLinqServerModeSource in combination with a GetData method that fetches 20 rows at a time, this is faster again.
However, using pLinqServerModeSource I am still not able to show the data in the columns.
Maybe you can look at my sample project and help me with that ?
Thanks
Hello Guido,
Thank you for the sample project. I tested your sample and see that it takes approximately 600 ms to load our Grid. This happens due to the DataSet implementation. It creates DefaultView when the Grid accesses it for the first time after a data source is assigned. I performed another test and placed the standard DataGridView onto your form. I got the same results - please see the attached video and modified sample project. As you can also see in the attached video, the Grid shows data immediately when I set DataSource for the second time. Thus, this behavior is related to the implementation of the standard DataSet class.
As for the PLinqServerModeSource issue, it requires a collection that implements the IEnumerable interface as a data source. As I can see, you set the Source property to the masterTable.AsEnumerable value:
However, it returns an IEnumrable collection of DataRow objects. The Grid shows values of DataRow object properties instead of values stored in a row. To change this behavior, you need to create an IEnumerable collection of objects:
class Customer { public int Id { get; set; } public string Name { get; set; } } List<Customer> customers = new List<Customer>(); private void button4_Click(object sender, EventArgs e) { label1.Text = "testing..."; label1.Update(); Stopwatch sw = new Stopwatch(); sw.Start(); //CreateDataTable(int.Parse(textBox1.Text)); for (int i = 0; i < int.Parse(textBox1.Text); i++) { customers.Add(new Customer() { Id = i, Name = "Name" + i }); } sw.Stop(); label1.Text = "loading data: " + sw.ElapsedMilliseconds; if (getDataTable == null) { getDataTable = masterTable.Clone(); } else { getDataTable.Clear(); } rowIndex = 0; } private void button2_Click(object sender, EventArgs e) { label2.Text = "testing..."; Update(); Stopwatch sw = new Stopwatch(); sw.Start(); gridControl1.DataSource = new PLinqServerModeSource() { Source = customers }; sw.Stop(); label2.Text = "Fillig grid: " + sw.ElapsedMilliseconds; }
Attached is a modified sample project that illustrates this suggestion.
Hello,
that is exact what I need to avoid. I cannot create classes like Customer.
I have no clue what the resultset is going to be every time
I am experimenting and found that the DataTable.DefaultView can be used by the GridView to display the rows with header and all, but it always creates a childlevel.
see
https://supportcenter.devexpress.com/ticket/details/t958016
and
https://supportcenter.devexpress.com/ticket/details/t957966
How can I get around that ?
Hello Guido,
Thank you for the clarification. Currently, there is no component or feature that would allow one to achieve all these requirements. As I mentioned before, the loading time is not related directly to our components. It's related to the DataSet implementation in .NET. Our Grid works in a similar way as the VCL Grid with GridMode enabled. It loads and displays only visible records as I mentioned earlier.
Could you please clarify how you populate your DataSet? I am asking since we have the UnboundSource component which is very similar to what you are looking for. It allows you to add required columns and display data dynamically in the UnboundSource.ValueNeeded event handler. However, it also requires you to write code that creates UnboundSource columns and loads data in the UnboundSource.ValueNeeded event handler.
For your convenience, I've created a small sample project that illustrates how to load data from a data table using UnboundSource.
Hello Sasha,
Thank you for the unbound source example.
I have incorporated the unbound code into my sample project, and attached it
I also put some code to get the DataRowCount of the GridView, and it seems it is equal to the masterTable.Rows.Count.
This suggests that the unbound source does loads all rows immediate into the GridView.
It does however seem to load fast.
You also state that the GridView works similar as the VCL grid, but there I do see a difference in the DataRowCount and the Rows.Count of the dataset. So I am not sure if this is correct.
To make sure the loading time in the grid is measured as correct as possible, I load the data into the DataTable just once, and use the same DataTable for every method of filling the GridView. I do see some differences there, especially when using a method for the first time which is important to me off course.
My masterTable is populated by a SqlDataAdapter that reads a table from my database, you can use any table from your database to test it. My table has 1.222.818 rows in it
in my test binding is faster using the unbound source, when the recordcount is about 340.000.
When I use the table with 1.222.818 rows then the standard binding seems faster again, it also works significant faster when filtering/sorting then the unbound source.
PLinkServerModeSource is faster, but shows not data, only empty rows. I managed to get it to show data and headers and all, but only in a childlevel, not on the mainlevel.
The PLinqServerModeSource combined with the GetData method is still the fastest by far, but unfortunate the GridView cannot show any content, only empty rows
You are right that the loading into the datatable takes the most time. Is there a solution for that ? Again I am thinking of Delphi where you could arange loading a small number of records when needed just by setting some properties. Again keep in mind that I have no clue of the query that will be executed, it can be different every time based on the choices made by the user
Hello Guido,
Thank you for the clarification.
The only way to decrease time taken to load data from a data base to the standard DataSet/DataTable is to load less data. Since you "have no clue of the query that will be executed", I am not sure how this can be possible. In any case, this question is not directly related to our components and I recommend that you look for a solution on common programming resources such as Stack Overflow.
What about our WinForms Data Grid, you can load and show data using one of the following concepts:
I already illustrated multiple techniques to load data and show it in the Grid:
As far as I can see in the attached sample project, you are still using PLinqServerModeSource but it doesn't show data. I mentioned why it happens in my previous messages and illustrated how to use PLinqServerModeSource in your scenario. This approach seems to be not suitable for you. As far as I understand, direct binding to data table and VirtualServerModeSource are not suitable either.
It appears that the most suitable approach is to use UnboundSource.
Unbound Source loads data using the UnboundSource.ValueNeeded event.
I tested your project and loading time with the standard binding is much greater than time to bind the Grid to Unbound Source. See the attached video. Filtering and sorting indeed take more time when you use an unbound source since it needs to load data from all rows in this case. It's not possible to filter all rows without loading them.
Yes, this approach is the fastest one, however, it requires you to create the correct IEnumerable collection. The standard DataTable doesn't provide such an API.
Taking this into account, I suggest that you use UnboundSource. You can show less data using the SetRowCount method. As far as I know, VCL Grid doesn't support filtering and sorting when it works in GridMode. Thus, you can disable this functionality as well.