|
Hi,
I suggest you study some examples, and observe your code as to what exactly
is going on. As in: how many ValueNeeded events do fire, and how many
items are visible at one time. If there is a mismatch, then that is the
problem. The basic concept is the DGV should only fire ValueNeeded for
items that have to be drawn.
BTW are you sure you want over 100 columns? and all those get/set properties?
it does not look right.
Also I don't like the two lists of properties, the only data you should
need is a list of items. Avoid redundancy!
|
|
|
|
|
Luc,
Thank you. MSDN has DataGridView_Samples.zip which contains two VirtualMode grid samples and a doc file covering VirtualMode a bit.
Part of samples from this file are also duplicated in MSDN doc code samples.
MSDN forums contains also some few messages about VirtualMode.
There is also a Chris Cells book. The sample code presented here is modified sample from this book.
My code is based on this information.
I have looked first 100 pages returned from google search.
I havent found any other information about DataGridView VirtualMode.
Pressing F11 in RowCount moves to next line after delay. So OnCellValueNeeded method not any other lines in my code are not called.
In real application I have wide Product tables which can contain 100 columns. They appear fine in wide LCD screen. Reducing number of columns to 50 causes also long delay.
I'm sorry for a bad sample. Below is minimal code to reproduce
8 sec delay issue.
using System;
using System.Windows.Forms;
class Test
{
public static void Main()
{
Application.Run(new VirtualModeForm());
}
}
class VirtualModeForm : Form
{
DataGridView grid = new DataGridView();
public VirtualModeForm()
{
Controls.Add(grid);
grid.VirtualMode = true;
grid.ColumnCount = 108;
grid.RowCount = 1000000;
}
}
Andrus
|
|
|
|
|
Hi Andrus,
I did a little experiment with your code. Observations:
- time elapsed is proportional to number of rows;
- time elapsed heavily depends (not proportional) on number of columns
- setting RowCount first is a lot faster.
Conclusions:
1) the DGV seems to create objects for all the cells right from
the start, and creating 108 million objects is bound to take a couple
of seconds.
2) for unknown reasons RowCount-first is faster
BTW: you should not add the grid to Controls before it has been set up.
|
|
|
|
|
Luc,
2) for unknown reasons RowCount-first is faster
Thank you very much. You are genious.
I tried this in my applicaton and this eliminates RowCount delay.
Now there is only 3 sec delay which is caused by reading first two pages to cache like in MSDN sample.
There is also SELECT COUNT(*) FROM mytable command but this seems not to cause any delay.
the DGV seems to create objects for all the cells right from
the start, and creating 108 million objects is bound to take a couple
108 millions of objects should take visible in Task Manager amout of memory. Task Manager memory (working set) does not show significat memory consumption.
So I think that 108 million of objects are not created.
Maybe this is related to sililar issue which posted here and in MS product feedback and which does not have any solution:
Steps to reproduce:
1. Run code below
2. Double click in grid header in separation line between columns 1 ja 2
Observed:
CPU usage goes to 100% for a long time.
using System;<br />
using System.Windows.Forms;<br />
using System.Collections.Generic;<br />
<br />
class test {<br />
[STAThreadAttribute()]<br />
public static void Main() {<br />
Application.Run(new VirtualModeForm());<br />
}<br />
}<br />
<br />
class VirtualModeForm : Form {<br />
private List<DataObject> m_Data = new List<DataObject>();<br />
private List<bool> m_Visited = new List<bool>();<br />
DataGridView m_Grid = new DataGridView();<br />
public VirtualModeForm() {<br />
Controls.Add(m_Grid);<br />
m_Grid.CellValueNeeded += OnCellValueNeeded;<br />
InitData();<br />
InitGrid();<br />
}<br />
<br />
private void InitData() {<br />
for (int i = 0; i < 1000001 + 1; i++) {<br />
m_Visited.Add(false);<br />
DataObject obj = new DataObject();<br />
obj.Id = i;<br />
obj.Val = 2 * i;<br />
m_Data.Add(obj);<br />
} }<br />
<br />
private void InitGrid() {<br />
m_Grid.Dock = DockStyle.Fill;<br />
m_Grid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCellsExceptHeader);<br />
m_Grid.VirtualMode = true;<br />
m_Grid.ReadOnly = true;<br />
m_Grid.ColumnCount = 3;<br />
m_Grid.Rows.Add();<br />
m_Grid.Rows.AddCopies(0, 1000000);<br />
}<br />
<br />
private void OnCellValueNeeded(object sender, DataGridViewCellValueEventArgs e) {<br />
<br />
m_Visited[e.RowIndex] = true;<br />
if (e.ColumnIndex == 0) {<br />
e.Value = m_Data[e.RowIndex].Id;<br />
} else if (e.ColumnIndex == 1) {<br />
e.Value = m_Data[e.RowIndex].Val;<br />
} else if (e.ColumnIndex == 2) {<br />
<br />
Random rand = new Random();<br />
e.Value = rand.Next();<br />
}<br />
}<br />
}<br />
<br />
public class DataObject {<br />
private int m_Id;<br />
private int m_Val;<br />
<br />
public int Val {<br />
get { return m_Val; }<br />
set { m_Val = value; }<br />
}<br />
<br />
public int Id {<br />
get { return m_Id; }<br />
set { m_Id = value; }<br />
}<br />
}
How to fix this ?
BTW: you should not add the grid to Controls before it has been set up.
I tried it but this does not to affect to speed at all.
My base class is created using Winforms designer which adds grid in form constructur. If I modify this code manually changes are lost when designer re-creates code.
Code sample of this is below.
Questions:
1. Why I should not add grid before setting ?
2. How to add grid only after it has set without modifying designer generated grid code manually to code below? I need to use subclassed form because main form contains generic type parameter and Winforms designer does not allow to design form with generic.
using System;<br />
using System.Windows.Forms;<br />
<br />
class Test<br />
{<br />
public static void Main()<br />
{<br />
Application.Run(new VirtualModeForm<Customer>());<br />
}<br />
}<br />
<br />
class VirtualModeForm<T> : BaseForm<br />
{<br />
public VirtualModeForm()<br />
{<br />
grid.VirtualMode = true;<br />
grid.RowCount = 1000000;<br />
grid.ColumnCount = 108;<br />
}<br />
}<br />
<br />
class Customer { }<br />
<br />
class BaseForm : Form<br />
{<br />
internal BaseForm()<br />
{<br />
InitializeComponent();<br />
}<br />
<br />
void InitializeComponent()<br />
{<br />
grid = new DataGridView();<br />
Controls.Add(grid);<br />
}<br />
protected DataGridView grid;<br />
}
Andrus
|
|
|
|
|
i am making an application which requires to call the telephone or mobile.
and i don't how to do this can any one pls help me.............
|
|
|
|
|
What research have you done? What products are you evaluating? What services have you checked out? What does the client require? Landline + mobile? How do you honestly expect anyone to answer effectively if you can't provide even a small amount of detail?
Bar fomos edo pariyart gedeem, agreo eo dranem abal edyero eyrem kalm kareore
|
|
|
|
|
The last time I did that I used a MODEM.
|
|
|
|
|
this is the first time I'm using message queue, but when trying to crate a message queue it says that message queue is not installed, do i have to install it separately or is it because my local machine is not a server .
|
|
|
|
|
To use message queuing the machine has to be added to an Active Directory domain, and MessageQueuing must be installed at the machine. This is to be found under "Add/remove windows components"
|
|
|
|
|
I'm working on a project where my application (in .net) should communicate with a java-application through MSMQ. By using BinaryMessageFormatter the java application could not deserialize the message, but this worked fine when using XmlMessageFormatter.
The problem is that this java application posts back an XML to the message queue, but i can't read this in any way.
I have the following code:
1 using (MessageQueue mq = new MessageQueue(".\\testQueue"))
2 {
3 mq.Formatter = new XmlMessageFormatter(new Type[] { typeof(string), typeof(XmlDocument), typeof(XmlElement), typeof(XmlDataDocument), typeof(XmlNode) });
4
5 using (Message msg = mq.Receive())
6 {
7 try
8 {
9 object o = msg.Body;
10 Console.WriteLine(o as string);
11 }
12 catch (Exception ex)
13 {
14 Console.WriteLine("Error: " + ex.Message);
15 }
16 finally
17 {
18 Console.ReadKey(true);
19 }
20 }
21 }
I just get an error message "There is an error in XML document (2,1)". Is there any way to "read the raw content" of a message, or any other way to get the content of the message?
The XML in the incoming queue starts like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<StatusSMSMessage xmlns="http://www........./specs/schemas/smsgw/StatusSMSMessage.xsd" mtMessageId="minimalMessage1"><DestinationAddress>
Do I have to implement message queuing from the Windows COM-library? In case; how to do this in .net?
|
|
|
|
|
I don't think you pass the right types.
You need to create your own type, like:
[XmlRoot(Namespace = "http://www........./specs/schemas/smsgw/StatusSMSMessage.xsd")]
class StatusSMSMessage
{
public StatusSMSMessage()
{
}
[XmlAttribute]
public string mtMessageId
{
get { ... }
set { ... }
}
}
And initialize your formatter:
mq.Formatter = new XmlMessageFormatter(new Type[] { typeof(StatusSMSMessage) });
This example is not exhaustive, I would read more on XML serialization if I were you.
|
|
|
|
|
I now have made my own type. The start is like this:
[XmlRoot("StatusSMSMessage", Namespace = "http://www....../specs/schemas/smsgw/StatusSMSMessage.xsd", IsNullable = false)]
public class StatusSMSMessage
{
public StatusSMSMessage() { }
[XmlAttribute("mtMessageId")]
public string mtMessageId;
....
(just removed some of the address inn the Namespace),
And i inizialize my XmlMessageFormatter like this:
using (MessageQueue mq = new MessageQueue(".\\" + qn))
{
mq.Formatter = new XmlMessageFormatter(new Type[] { typeof(StatusSMSMessage) });
...
But when i try to read the message like
object o = message.Body;
I get the message "Root element missing", but i know the message starts with
<?xml version="1.0" encoding="ISO-8859-1"?>
<StatusSMSMessage xmlns=...
I'm totally new at XML Serialization. Does anyone have a clue to why I get this error message?
|
|
|
|
|
Could you paste the entire code for your class? And also the root node of your messge, including the entire namespace?
|
|
|
|
|
Actually I solved it in a different way. Instead i used the ActiveXMessageFormatter, and got the message as plain text, and just used XmlDocument.LoadXml() to get it into an xml document.
Anyway; thanks for your time
|
|
|
|
|
Hello everyone!!!
I need to do a job to college that consists in build a simple file allocation table (FAT) emulator...
The FAT itself will be a simple unidimentional array.. and it just have to do basic operations of a very Basic File System (create, remove, update and delete files)
I´d like to do something ellegant with a friendly GUI containing the array and buttons wich triggers the operations.. Something simple and preety.... Can be C#, C++... C#´s most welcome!!!
Do anyone know something good to start reading about? Someone did somehing like? I´m already searching by the way but found nothing reliable to start....
Thanks
|
|
|
|
|
Operating system ..... any good text book
|
|
|
|
|
not reliable.... just tanembaum and deitel.....
i´d like something more....
|
|
|
|
|
It's not going to be too easy, but a FAT documentation[^] and perhaps some existing (non C#) code should do the job.
FAT is not really complex compared with newer file systems.
regards
modified 12-Sep-18 21:01pm.
|
|
|
|
|
Hi
Does anyone know how to delete an item in a ListBox and then, select the next one or previous one in the listbox?
Currently, I was using the next code:
int index = listBox1.SelectedIndex;
listBox1.Items.RemoveAt(index);
Reestablecer();
int cuenta = listBox1.Items.Count;
if (index < cuenta)
{
index++;
listBox1.SelectedIndex = index;
}
else
{
index--;
listBox1.SelectedIndex = index;
}
but i have a event on SelectedIndexChanged on the ListBox, so when I delete the item in the listbox, automatically the code on the SelectIndexChanged is executed and i get errors because the value of the property listbox.selecteditem is null.
Any ideas of how to solve it?
thanks in advance.
~ Bizarre what men fin attractive ~
|
|
|
|
|
When you have written this code ?
Did you try to catch last removed index value in SelectIndexChanged and manipulated your existing code as you mentioned
int cuenta = listBox1.Items.Count;
if (index < cuenta)
{
index++;
listBox1.SelectedIndex = index;
}
else
{
index--;
listBox1.SelectedIndex = index;
}
Parwej Ahamad
g.parwez@gmail.com
|
|
|
|
|
Your problem is the remove index, when you remove an item you automatically move everything up so don't need to change selected index
|
|
|
|
|
I tried to only remove the item, but the program still executes the selectindexchanged statement.
I get the error NullRefefenceException.
~ Bizarre what men fin attractive ~
|
|
|
|
|
int index = listBox1.SelectedIndex;
if (index >= 0)
{
listBox1.Items.RemoveAt(index);
Reestablecer();
int lastItem = listBox1.Items.Count - 1;
if (index > lastItem)
{
listBox1.SelectedIndex = lastItem;
}
}
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
your code worked fine! Now i just need to check it few more times, because after i delete few items it gets again the null reference exception
thank you
~ Bizarre what men fin attractive ~
|
|
|
|
|
Try this:
int index = listBox1.SelectedIndex;
if (index >= 0)
{
listBox1.Items.RemoveAt(index);
Reestablecer();
int lastItem = listBox1.Items.Count - 1;
if (lastItem >= 0)
{
if (index > lastItem)
{
listBox1.SelectedIndex = lastItem;
}
}
else
{
listBox1.SelectedIndex = -1;
}
}
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|