I tried your code and got the following issue: Observed: After activating second window grid current record marker jumps to first row:
> test
*
Exprected: Current row marker should remain in last row:
test
*
Andrus
I tried your code and got the following issue: Observed: After activating second window grid current record marker jumps to first row:
> test
*
Exprected: Current row marker should remain in last row:
test
*
Andrus
Thank you. Two issues: 1. In real-application second form may be activated when some other form, not this form containing grid is activated. There may be also a lot of forms like first form. How to use deactivate in this case? 2. If second form is activated, grid in first form visually shows that current row is first row by putting triangle to first row. How to prevent this so that current row triangle remains in second, new row ?
Andrus
To reproduce: 1. Run code 2. Press down arrow 3. Click in second form title 4. Click in first form title 5. Enter some characters Observed: Entered data appears in first row Expected: Entered data should appear in second row How to fix ? using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms; class TestApplication { static void Main() { var p = new Form(); p.IsMdiContainer = true; p.WindowState = FormWindowState.Maximized; var f1 = new TestForm(); var f2 = new Form(); f2.MdiParent = p; f1.MdiParent = p; f1.Show(); f2.StartPosition = FormStartPosition.Manual; f2.Left = 300; f2.Show(); Application.Run(p); } } class TestForm : Form { internal DataGridView grid = new DataGridView(); internal List<Customer> list; public TestForm() { Controls.Add(grid); BindingSource BindingSource = new BindingSource(); list = new List<Customer>(); list.Add(new Customer() { Name = "test" }); BindingList<Customer> bindingList = new BindingList<Customer>(list); BindingSource.DataSource = bindingList; grid.DataSource = bindingList; } } class Customer { public string Name { get; set; } }
Andrus
MSDN DataGridView VirtualMode with caching sample code DataRetriever loads two pages always to cache thus making 2 database accesses. If datagridview uses one page of data, second page retrieval is unnessecary and makes DataGridView display 2 times slower. How to change this sample code so that only one page is loaded initially and second is loaded on real demand only ? How to change this code so that it allows more than 2 pages of cached data? 2 page limit seems to be hardcoded into this page. Or is there some other sample code which has solved those issues ? Andrus.
Andrus
To reproduce: 1. Run code. 2. Enter some data to grid 3. Click other form caption 4. Click original form caption 5. Enter some characters Observed: entered characters are ignored Expected: entered characters must appear in last active textbox How to fix ? Andrus. using System.Windows.Forms; using System.Collections.Generic; using System; public class Test { static void Main() { Application.Run(new MainForm()); } } class MainForm : Form { public MainForm() { WindowState = FormWindowState.Maximized; IsMdiContainer = true; Form frm = new Childform(); frm.MdiParent = this; frm.Show(); Form frm2 = new Childform(); frm2.MdiParent = this; frm2.Show(); frm2.Left = 2000; } } class Childform : Form { DataGridView grid; Control LastFocus = null; public Childform() { ToolStripContainer tc = new ToolStripContainer(); grid = new DataGridView(); grid.Columns.Add(new DataGridViewTextBoxColumn()); grid.EditMode = DataGridViewEditMode.EditOnEnter; grid.Top = 120; grid.Height = 300; Controls.Add(tc); tc.ContentPanel.Controls.Add(new MyUserControl()); tc.ContentPanel.Controls.Add(grid); this.Activated += new EventHandler(Childform_Activated); this.Deactivate += new EventHandler(Childform_Deactivate); } void Childform_Activated(object sender, EventArgs e) { if (this.LastFocus != null) this.LastFocus.Focus(); } void Childform_Deactivate(object sender, EventArgs e) { this.LastFocus = this.ActiveControl; while (LastFocus is IContainerControl) LastFocus = ((IContainerControl)LastFocus).ActiveControl; } } class MyUserControl : UserControl { internal MyUserControl() { Height = 100; Controls.Add(new TextBox()); } }
Andrus
How to activate last textbox in DataGridView on re-activate ? I created testcase for it: 1. Run code. 2. Enter some data to grid 3. Click other form caption 4. Click original form caption 5. Enter some characters Observed: entered characters are ignored Expected: entered characters must appear in last cell before form activation How to fix ?
using System.Windows.Forms;
public class Test
{
static void Main()
{
Application.Run(new MainForm());
}
}
class MainForm : Form
{
public MainForm()
{
WindowState = FormWindowState.Maximized;
IsMdiContainer = true;
Form frm = new Childform();
frm.MdiParent = this;
frm.Show();
Form frm2 = new Childform();
frm2.MdiParent = this;
frm2.Show();
frm2.Left = 2000;
}
}
class Childform : Form
{
public Childform()
{
var grid = new DataGridView();
grid.Columns.Add(new DataGridViewTextBoxColumn());
grid.EditMode = DataGridViewEditMode.EditOnEnter;
Controls.Add(grid);
}
}
Andrus
How to get syntactically correct signature which compiles for code template grneration ? I tried code below but it creates syntactically incorrect signature.
using System;
using System.Collections.Generic;
public class MainClass
{
static string GetSignature(Type xTheType, string method)
{
var xModule = xTheType.Module;
var xTheMethod = xTheType.GetMethod(method);
return xTheMethod.ToString();
}
public static void Main()
{
// Observed: Void Test(System.Object, System.Collections.Generic.List\`1\[System.String\])
// Expected: public void Test(object p1, List<string> p2)
// or some other syntactically correct signature
Console.WriteLine(GetSignature(typeof(MainClass), "Test"));
}
public void Test(object p1, List<string> p2)
{
}
}
Andrus
I have UserControls in MDI child forms containing TextBoxes and other controls. When user re-activates form, I need that Control which was last activated is activated again. Currently *first* control is activated always. To reproduce: 1. Run code. 2. Make TextBox2 as current TextBox by selecting its text 3. Activate other form 4. Activate previous form by clicking in form title bar Observed: TextBox1 receives focus Expected: TextBox2 should receive focus How to force UserControl to forward focus to child its current child control (TextBox2) ? using System.Windows.Forms; public class Test { static void Main() { Application.Run(new MainForm()); } } class MainForm : Form { public MainForm() { WindowState = FormWindowState.Maximized; IsMdiContainer = true; Form frm = new Childform(); frm.MdiParent = this; frm.Show(); Form frm2 = new Childform(); frm2.MdiParent = this; frm2.Show(); frm2.Left = 2000; } } class Childform : Form { public Childform() { Controls.Add(new Mycontrols()); } } class Mycontrols : UserControl { public Mycontrols() { TextBox tb1 = new TextBox(); tb1.Text = "TextBox1"; TextBox tb2 = new TextBox(); Controls.Add(tb1); tb2.Top = 100; tb2.Text = "TextBox2"; tb2.Select(); Controls.Add(tb2); } }
Andrus
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; using System.Windows.Forms; using System.Collections.Generic; class test { [STAThreadAttribute()] public static void Main() { Application.Run(new VirtualModeForm()); } } class VirtualModeForm : Form { private List<DataObject> m_Data = new List<DataObject>(); private List<bool> m_Visited = new List<bool>(); DataGridView m_Grid = new DataGridView(); public VirtualModeForm() { Controls.Add(m_Grid); m_Grid.CellValueNeeded += OnCellValueNeeded; InitData(); InitGrid(); } private void InitData() { for (int i = 0; i < 1000001 + 1; i++) { m_Visited.Add(false); DataObject obj = new DataObject(); obj.Id = i; obj.Val = 2 * i; m_Data.Add(obj); } } private void InitGrid() { m_Grid.Dock = DockStyle.Fill; m_Grid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCellsExceptHeader); m_Grid.VirtualMode = true; m_Grid.ReadOnly = true; m_Grid.ColumnCount = 3; m_Grid.Rows.Add(); m_Grid.Rows.AddCopies(0, 1000000); } private void OnCellValueNeeded(object sender, DataGridViewCellValueEventArgs e) { m_Visited[e.RowIndex] = true; if (e.ColumnIndex == 0) { e.Value = m_Data[e.RowIndex].Id; } else if (e.ColumnIndex == 1) { e.Value = m_Data[e.RowIndex].Val; } else if (e.ColumnIndex == 2) { Random rand = new Random(); e.Value = rand.Next(); } } } public class DataObject { private int m_Id; private int m_Val; public int Val { get { return m_Val; } set { m_Val = value; } } public int Id { get { return m_
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;
// this line causes 8 seconds delay.
grid.RowCount = 1000000;
}
}
Andrus
Mika, thank you for reply. Tried tried the following: 1. OnCellValueNeeded is not called: F11 steps to next line after 8 sec delay. Debug output window shows a lot of messagers "skipping over non-user code". Delay seems to occur after those messages are output. 2. I removed m_Grid.AutoResizeColumns line and tried with DataGridViewAutoSizeColumnsMode.None Delay still occurs. I'm wondering why number or rows affects to this delay. VirtualMode must be designed to avoid this. Is it possible to use other control to create editable virtual grid ? I looked SourceGrid in http://www.devage.com/[^] but it last update was a year ago so it seems not maintained. Those grids are used frequently in my application in UI. Data for visibla part of a grid grid is retrieved from database for 4 seconds due to virtualization. It is not reasonable to force user to wait 8 seconds for a grid to render. Any idea how to fix this ?
Andrus
Lyc, as you see from my sample it already uses VirtualMode. The issue is that increasing number of rows decreases RowCount setting speed. This should not happen.
Andrus
Fake Rowcount causes the following issues: 1. It is not possible to see more rows: you can navigate only between first 100 rows. No way to go to row number 101. 2. Buttor in vertical scrollbar does not show real position in table. For real rowcount, button indicates visually real position: in the start, in middle or in end of table. So it is impossible to use fake rowcount.
Andrus
In code below Line m_Grid.RowCount = 1000000; takes 8 seconds. How to speed it up ? Andrus.
using System;
using System.Windows.Forms;
using System.Collections.Generic;
class test
{
[STAThreadAttribute()]
public static void Main()
{
Application.Run(new VirtualModeForm());
}
}
class VirtualModeForm : Form
{
private List<DataObject> m_Data = new List<DataObject>();
private List<bool> m_Visited = new List<bool>();
DataGridView m_Grid = new DataGridView();
public VirtualModeForm()
{
Controls.Add(m_Grid);
m_Grid.CellValueNeeded += OnCellValueNeeded;
InitData();
InitGrid();
}
private void InitData()
{
for (int i = 0; i < 1000001 + 1; i++)
{
m\_Visited.Add(false);
DataObject obj = new DataObject();
obj.Id = i;
obj.Val = 2 \* i;
m\_Data.Add(obj);
}
}
private void InitGrid()
{
m\_Grid.Dock = DockStyle.Fill;
m\_Grid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCellsExceptHeader);
m\_Grid.VirtualMode = true;
m\_Grid.ReadOnly = true;
m\_Grid.ColumnCount = 108;
// this line causes 8 seconds delay. how to fix.
m\_Grid.RowCount = 1000000;
}
private void OnCellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
m\_Visited\[e.RowIndex\] = true;
if (e.ColumnIndex == 0)
{
e.Value = m\_Data\[e.RowIndex\].Id;
}
else if (e.ColumnIndex == 1)
{
e.Value = m\_Data\[e.RowIndex\].Val;
}
else if (e.ColumnIndex == 2)
{
Random rand = new Random();
e.Value = rand.Next();
}
}
}
public class DataObject
{
private int m_Id;
private int m_Val;
public int Val
{
get { return m\_Val; }
set { m\_Val = value; }
}
public int Id
{
get { return m\_Id; }
set { m\_Id = value; }
}
public int Id1 { get; set; }
public int Id2 { get; set; }
public int Id3 { get; set; }
public int Id4 { get; set; }
public int Id5 { get; set; }
public int Id6 { get; set; }
public int Id7 { get; set; }
public int Id8 { get; set; }
public int Id9 { get; set; }
public int Id10 { get; set; }
public int Id11 { get; set; }
public int Id12 { get; set;
I have DataGridView in virtual mode containing 3500 rows. In code below, assigning to RowCount value to 3500 takes 8 seconds. CPU usage goes high at this time. Stepping by F11 into user code shows few celltemplate property getters and combobox/datecombo constructor calls without database access which does not take a lot of time. Debug output (below) shows lot of messages Stepping over non-user code. Running in release mode from Windows this line speed is same (slow). How to speed up grid creation ? Using C# Express 2008 3.5 SP1 in Vista.
class Grid : System.Windows.Forms.DataGridView {
internal void SetDataRetriever(DataRetriever<TEntity> dataRetriever)
{ ......
SuspendLayout();
Enabled = false;
int cnt = DataRetriever.RowCount + (ReadOnly ? 0 : 1);
// next line takes 8 seconds:
RowCount = cnt;
Enabled = true;
ResumeLayout();
}
protected override void
OnCellValueNeeded(DataGridViewCellValueEventArgs e)
{
if (!Enabled)
return;
...
}
protected override void OnRowEnter(DataGridViewCellEventArgs e)
{
if (!Enabled)
return;
...
}
}
Debug output window contains: Step into: Stepping over non-user code 'System.Windows.Forms.DataGridView.RowCount.set' Step into: Stepping over non-user code 'System.Windows.Forms.DataGridViewColumn.CellTemplate.get' Step into: Stepping over non-user code 'System.Windows.Forms.DataGridView.CompleteCellsCollection' Step into: Stepping over non-user code 'System.Windows.Forms.DataGridViewColumn.CellTemplate.get' Step into: Stepping over non-user code 'System.Windows.Forms.DataGridView.CompleteCellsCollection' Step into: Stepping over non-user code 'System.Windows.Forms.DataGridViewTextBoxCell.DataGridViewTextBoxCell' Step into: Stepping over non-user code 'System.Windows.Forms.PropertyStore.GetObject' Step into: Stepping over non-user code 'System.Windows.Forms.DataGridViewCell.Style.get' Step into: Stepping over non-user code 'System.Windows.Forms.DataGridViewTextBoxCell.Clone' Step into: Stepping over non-user code 'System.Windows.Forms.DataGridView.CompleteCellsCollection' Step into: Stepping over non-user code 'System.Windows.Forms.DataGridViewColumn.CellTemplate.get' Step into: Stepping over non-user code 'System.Windows.Forms.DataGridView.CompleteCellsCollection'
I use Winforms RichTextBox control to edit scripts. Scripts are plain ascii texts. When error occurs, script engine returns character position of error in code as integer. How to position cursor to this character position ? RichTextBox does not have current position property.
Andrus
Thank you. I found this thread http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/32649965654df408/57ba3e39a6c2711f?lnk=st&q=#57ba3e39a6c2711f[^] which described that using regular expressions is not easy for this. Can yuo provide sample how to use regexps for this ?
Andrus
I need to implement vfp function which uses * and ? wildcards:
static bool Like( cExpression1, cExpression2)
cExpression1 Specifies the character expression that Like( ) compares with cExpression2. cExpression1 can contain the wildcards such as * and ?. The question mark (?) matches any single character in cExpression2 and the asterisk (*) matches any number of characters. You can mix any number of wildcards in any combination in cExpression1. cExpression2 Specifies the character expression LIKE( ) compares with cExpression1. returns true on wildcards match. How to implement this ?
Andrus
I need to get sql command text where parameters are replaced by values. I tried code below but displayed sql statement contains parameter names, not actual values. How to obtain command where parameters are replaced by their values ? Andrus.
static IDataReader ExecuteReader(string command
, out IDbConnection connection
, CommandBehavior behavior
, params IDbDataParameter[] dataParams)
{
connection = ...
connection.Open();
IDbCommand cmd = new SqlCommand(command, connection as
SqlConnection);
foreach (IDbDataParameter p in dataParams)
cmd.Parameters.Add(p);
// How to display replaced parameter values ?
MessageBox.Show(cmd.CommandText);
return cmd.ExecuteReader(behavior |
CommandBehavior.CloseConnection);
}
Andrus
Yes. I'm sorry my previous letter was wrong, f format cannot used. I want that result string contains as may decimal places after comma as decimal value actually contains *except* zero must be converted to empty string. ToString() without argument, with empty format string or with G format as you demostrated produces this output except it outputs 0m as 0 : 0.400m is converted to 0.400 123.40m is converted to 123.40 123.4m is converted to 123.4 0m is converted to 0 How to create format string which works as above except 0m, 0.00m etc is converted to empty string ? I tried ";;#" format string but this does not output any digits. I'm using FYI RDL report engine which allows to use only .NET format strings, no code.
Andrus