I'm having problem with binding Hscroll to datagridview. I need to have bigger scoll, than default DGV one. So i need to bind custom scroll to dgv or increase height of default one. I'm using WinForms.
I have tried the following code, but it doesnt fit my needs, the scroll stopped in middle of my dgv, manipulating values had no effect on it.
private void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
int totalwidth = dataGridView1.RowHeadersWidth;
for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
totalwidth += dataGridView1.Columns[i].Width ;
}
hScrollBar1.LargeChange = dataGridView1.Width;
hScrollBar1.SmallChange = dataGridView1.Columns[gsKodTowaruDataGridViewTextBoxColumn.Index].Width;
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
{
hScrollBar1.Value = e.NewValue;
}
}
private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
{
dataGridView1.HorizontalScrollingOffset = e.NewValue;
}
Thanks for answers.
You have to bind these values to react to change right?
You are using a maxWidth value without using it.
Also, you should react to Resize Event on the DataGridView to make sure the HScroll values do change.
Related
I have a simple form with RightToLeft = true.
in the form there is a panel with AutoScroll = true. and in the panel there is a DataGridView with a very long width (2000px).
user can add columns by clicking "Add Column" Button.
this is code of "Add column" button click event:
private void button1_Click(object sender, EventArgs e)
{
_index++;
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn() { Name = $"Col{_index}",HeaderText = $"Col{_index}"});
}
the problem is: when user add some columns and clicks on one of ColumnHeader's border for first time to drag it and resize the column the panel will be scrolled to end left and column will be very wide that is not naturally my desired behavior. in the next clicks and resizing every thing works perfect.
how can i resolve this problem?
thanks
You can resize the columns each time you add a new one
you can check this
PS : Make sure to set Row Header to false so there will be no conflict with the grid width
private void updateWidth()
{
foreach (DataGridViewColumn item in dataGrid.Columns)
{
item.Width = dataGrid.Columns.Count == 0 ?
dataGrid.Width
: (int)(dataGrid.Width / dataGrid.Columns.Count);
}
}
int _index = 0;
private void button1_Click(object sender, EventArgs e){
var col = new DataGridViewColumn();
col.Name = $"Col{_index++}";
col.CellTemplate = new DataGridViewTextBoxCell();
dataGrid.Columns.Add(col);
updateWidth();
}
}
For a fixed width you can do ( with AutoSizeColumnsMode set to None):
int _index = 0;
int fixedWidth = 200;
private void button1_Click(object sender, EventArgs e)
{
var col = new DataGridViewColumn();
col.Name = $"Col{_index++}";
col.Width = fixedWidth;
col.CellTemplate = new DataGridViewTextBoxCell();
dataGrid.Columns.Add(col);
}
i create a subclass datagridview to override the mousewheel event to catch mouse scroll then send key UP or DOWN. i create a datatable to be bind as datasource for mydatagridview by button click
private void button1_Click(object sender, EventArgs e)
{
DataTable myDataTable = new DataTable();
int NUM_ROWS = 150;
int NUM_COLS_TO_CREATE = 10;
for (int i = 0; i < NUM_COLS_TO_CREATE; i++)
{
myDataTable.Columns.Add("x" + i, typeof(string));
}
for (int i = 0; i < NUM_ROWS; i++)
{
var theRow = myDataTable.NewRow();
for (int j = 0; j < NUM_COLS_TO_CREATE; j++)
{
theRow[j] = "whatever";
}
//add the row *after* populating it
myDataTable.Rows.Add(theRow);
}
MyDataGridView1.DataSource = myDataTable;
}
the code that override the mousewheel event as this
public partial class MyDataGridView : DataGridView
{
protected override void OnMouseWheel(MouseEventArgs e)
{
if (e.Delta < 0)
SendKeys.Send("{DOWN}");
else
SendKeys.Send("{UP}");
}
}
Its working fine if we use mouse wheel to scroll each item in a SLOW way, but if you scroll too FAST using the mouse wheel, somewhat the datagridview becomes lagging.
As example from row 1 to 5, it will jump the row from 1 to 3,then 3 to 5 something like that, here come another weird issue. i use "Navicat" a lot in my daily basis..
so if i open both my application and Navicat. the mouse wheel scrolling now become very smooth on my application even if i scroll too fast. but then if i close Navicat then scrolling become lagging again. what was causing this? i am very sorry if i cant explained it well, all i want is just want to makes the scrolling each item smooth. Any suggestion?
as #Bozhidar mentioned that i should better handling the MouseWheel event instead or overriding it. so i've come up with the solution just in case anyone need it too.
in Form_Load add
MyDataGridView1.MouseWheel += new MouseEventHandler(MyDataGridView1_MouseWheel);
then place this anywhere inside your class
private void MyDataGridView1_MouseWheel(object sender, MouseEventArgs e)
{
HandledMouseEventArgs hme = (HandledMouseEventArgs)e;
hme.Handled = true;
int rowIndex = MyDataGridView1.CurrentCell.RowIndex;
int cellIndex = MyDataGridView1.CurrentCell.ColumnIndex;
MyDataGridView1.CurrentCell = MyDataGridView1.Rows[e.Delta < 0 ? Math.Min(rowIndex + 1, MyDataGridView1.RowCount - 1) : Math.Max(rowIndex - 1, 0)].Cells[cellIndex];
}
The SendKeys method is not as reliable when it comes to precise timing - see the official documentation. Try setting the "SendKeys" app setting to "SendInput" in order to force the new behavior.
But you'd be better off handling the MouseWheel event instead of overriding it. You need to hook it by hand - not sure why it isn't present into the Property Window. Given your DataGridView is named dgv:
private void Form1_Load(object sender, EventArgs e)
{
dgv.MouseWheel += Dgv_MouseWheel;
}
Next, have you considered FirstDisplayedScrollingRowIndex? Just set it as appropriate in the event, and set the Handled flag, like this:
private void dgv_MouseWheel(object sender, MouseEventArgs e)
{
dgv.FirstDisplayedScrollingRowIndex += 3;
var he = (HandledMouseEventArgs);
he.Handled = true;
}
Here's an approach that preserves the default scrolling behavior of scrolling the viewport, but not changing the row selection.
It also performs much faster than the built-in mouse wheel handler when millions of rows are being handled in a virtual grid:
private void Form1_Load(object sender, EventArgs e)
{
DataGridView1.MouseWheel += DataGridView1_MouseWheel;
}
private void DataGridView1_MouseWheel(object sender, MouseEventArgs e)
{
var hme = e as HandledMouseEventArgs;
hme.Handled = true;
int displayedRowIndex = DataGridView1.FirstDisplayedScrollingRowIndex;
// each "detente" scroll appears to create a delta of 120
// dividing delta by 120 to get the number of rows scrolled
// taking the negative of the delta so that it can be added to the displayedRowIndex intuitively as negative is down, positive is up
var rowDelta = -(e.Delta / 120);
var newDisplayedRowIndex = e.Delta < 0 ? Math.Min(displayedRowIndex + rowDelta, DataGridView1.RowCount - 1) : Math.Max(displayedRowIndex + rowDelta, 0);
DataGridView1.FirstDisplayedScrollingRowIndex = newDisplayedRowIndex;
}
how horizontal scroll using button in datagridview?
dotaz2AdvancedDataGridView.HorizontalScrollingOffset = dotaz2AdvancedDataGridView.HorizontalScrollingOffset + 30;
and,how to back scroll in datagridview?
If i understand your questions correctly you are asking how to scroll a datagridview sideways when pressing a button?
If so, you could do something like this:
public void Right(object sender, Eventargs e)
{
dotaz2AdvancedDataGridView.HorizontalScrollingOffset = dotaz2AdvancedDataGridView.HorizontalScrollingOffset + 30;
}
public void Left(object sender, Eventargs e)
{
dotaz2AdvancedDataGridView.HorizontalScrollingOffset = dotaz2AdvancedDataGridView.HorizontalScrollingOffset - 30;
}
Then you just need to assign these events to the buttons you would like to use
What event shall I use in a DataGridView considering that the DataGridView is full of data and when I click a row of data automatically I would like to retrieve all the data. I've tried using the event CellContentClick but it is only activated when I select a column data instead of a row
private void dtSearch_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
I have used the following to good effect. I handle the MouseDown event for the DataGridView and set the full row to be highlighted so that it is obvious it has been selected (unless of course you already have your full rows being selected).
private void dtSearch_MouseDown(object sender, MouseEventArgs e)
{
// Get the cell that was clicked from the location of the mouse pointer
DataGridView.HitTestInfo htiSelectedCell = dtSearch.HitTest(e.X, e.Y);
if (e.Button == MouseButtons.Left)
{
// Make sure that a cell was clicked, and not the column or row headers
// or the empty area outside the cells. If it is a cell,
// then select the entire row, set the current cell (to move the arrow to
// the current row)
//if (htiSelectedCell.Type == DataGridViewHitTestType.Cell)
if (htiSelectedCell.Type == DataGridViewHitTestType.RowHeader)
{
// do stuff here
}
}
}
Hows about the RowHeaderMouseClick.
Try using the CellClick event, and loop through the columns retrieving the row values you want:
private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);
}
public void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
List<object> values = new List<object>();
int cols = this.dataGridView1.Columns.Count;
for (int col = 0; col < cols; col++)
{
values.Add(this.dataGridView1[col, e.RowIndex].Value);
}
}
I have a checkedlistbox and a listbox both the same height with the same number of items in them. I use the listbox to hold status of checkedlistbox a item.
If there's a scrollbar, then scrolling the checkedlistbox should also scroll the listbox with the same index. I kind of got that working except they scroll at different amounts.
private void checkedListBox1_MouseWheel(object sender, MouseEventArgs e)
{
int scroll = e.Delta / 120;
if (scroll == 1)
{
checkedListBox1.TopIndex -= 5;
listBox1.TopIndex = checkedListBox1.TopIndex;
}
else if (scroll == -1)
{
checkedListBox1.TopIndex += 5;
listBox1.TopIndex = checkedListBox1.TopIndex;
}
}
Additionally, I'm using this code to get the same indexes selected but there's a slight lag until the listbox index gets selected after selecting from the checkedlistbox. Anyway to make it select at the same time?
private void checkedListBox1_MouseClick(object sender, MouseEventArgs e)
{
if (checkedListBox1.Items.Count > 0)
{
int selected = checkedListBox1.SelectedIndex;
if (checkedListBox1.GetItemChecked(selected) == false)
{
checkedListBox1.SetItemChecked(selected, true);
listBox1.SetSelected(selected, true);
}
else if (checkedListBox1.GetItemChecked(selected) == true)
{
checkedListBox1.SetItemChecked(selected, false);
listBox1.SetSelected(selected, true);
}
}
}
You can put listboxes inside Two scrollviewer and in the viewChanged event write the code on xaml.cs part
private void ScrollViewer1_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
ScrollViewer2.ScrollToHorizontalOffset(double.Parse(ScrollViewer1.HorizontalOffset.ToString()));
}
http://www.codeguru.com/cpp/controls/listview/article.php/c4163
http://www.codeproject.com/Tips/197335/Synchronized-ListBox-objects-or-how-to-scroll-2-Li