C# windows form 2 gridviews with synced scroll - c#

I am developing an application in which two datagridviews are being populated from different data sources. I would like to have a single vertical scroll-bar that will make both gridviews work at the same time (scroll up and down together)
can anyone tell me how or direct me to a good tutorial.

If you have dgv1 and dgv2, you can create something like
dgv1.Scroll += new System.Windows.Forms.ScrollEventHandler(dgv1_Scroll);
Then, in dgv1_Scroll method, you can use FirstDisplayedScrollingRowIndex property:
dgv2.FirstDisplayedScrollingRowIndex = dgv1.FirstDisplayedScrollingRowIndex
Of course, if dgv's have different ammount of rows, you need to avoid IndexOutOfRange exception by checking each dgv rows count.

Use HorizontalScrollingOffset (or VerticalScrollingOffset).
this.dataGridViewDataSample.HorizontalScrollingOffset

I believe you can set up an event-like scenario, where whenever scrollbar A's "value" changes, change scrollbar B to the appropriate value as well.
(Note that value is a property of a scroll bar, I do not mean the value of the data inside the container.)
Please see the following msdn article regarding that property of a scroll bar for better reference:
http://msdn.microsoft.com/en-us/library/system.windows.forms.scrollbar.value.aspx
And the class itself --
http://msdn.microsoft.com/en-us/library/system.windows.forms.scrollbar.aspx

You could put the DataGridViews in Panels and use this:
public Form1()
{
InitializeComponent();
panel1.Scroll += new ScrollEventHandler(panel1_Scroll);
}
void panel1_Scroll(object sender, ScrollEventArgs e)
{
panel2.AutoScrollPosition = new Point(0,e.NewValue);
}
Unfortunately it does not seem that DataGridView has this property.

http://www.xs4all.nl/~wrb/Articles_2010/Article_DataGridViewScroll_01.htm
This link shows exactly what I needed and worked fine for me. The only problem I have now is that the datagrids does not have same rows in it. So even when one finishes (no more to scroll) the other must be able to continue.
Any suggestions?

take a look at this. i wanted to sync two listviews when i scroll any of them. u can achieve this using custom controls. code works like a charm.

_dataGridViewInput.Scroll += new ScrollEventHandler(_dataGridViewInput_Scroll);
_dataGridViewOutput.Scroll += new ScrollEventHandler(_dataGridViewOutput_Scroll);
void _dataGridViewInput_Scroll(object sender, ScrollEventArgs e)
{
this._dataGridViewOutput.FirstDisplayedScrollingRowIndex = this._dataGridViewInput.FirstDisplayedScrollingRowIndex;
}
void _dataGridViewOutput_Scroll(object sender, ScrollEventArgs e)
{
this._dataGridViewInput.FirstDisplayedScrollingRowIndex = this._dataGridViewOutput.FirstDisplayedScrollingRowIndex;
}

Related

Windows Forms C# - Make DataGridView push down other controls as rows are added

I have a handful of different DGV's that all need to be displayed on the same tab in my form. Sometimes the forms will have nothing added to them, others will have many rows added to them. I have tried using a TableLayoutPanel, a FlowLayoutPanel, and a regular Panel to hold all my containers/controls, and have tried various settings of "Dock: Fill; Dock: Top" and "Grow: True" but I cannot seem to find the right combination of controls and properties.
I am about to resort to trying to handle this programatically, but if I could handle exclusively in properties that would be great.
My resolution was to use a TableLayoutPanel, and programmatically grow each DGV as rows are added, which will force the panel that is containing the DGV to grow and push down the following cells.
My C# code for those who would really like to see it (haha):
private void AddFeature_Click(object sender, EventArgs e)
{
presenter.AddFeature_Click();
presenter.GrowDataGridView(FeatureGridView);
}
public void AddFeature_Click()
{
if (view.BindingSource == null)
{
return;
}
AddFeatureRow((DataTable)(view.BindingSource.DataSource));
}
public void GrowDataGridView(DataGridView dgv)
{
dgv.Height += 22;
}

WPF Datagrid focus and highlighting last row

I would like to highlight my lastly new create row in my Data grid, I have reference this page http://social.technet.microsoft.com/wiki/contents/articles/21202.wpf-programmatically-selecting-and-focusing-a-row-or-cell-in-a-datagrid.aspx to get some idea.
According to the reference link above datagrid first have to visualise . The reason of the last row is not focus and high light, might be cause by this reason.
Following is my code structure
private void CommitRow(object sender, DataGridRowEditEndingEventArgs e )
{
//FIRE WHEN ROW IS DONE EDIT
/*
STORING DATA TO DATABASE
*/
SelectRowByIndex(Datagrid, Datagrid.Items.Count - 1); //I refer from msdn blog
}
I tried to put the code SelectRowByIndex into a button , it will highlight the last row. Therefore I believe the code will only work when the grid is show up on UI.
My question is how to highlight the last row before interface is show up? or is that any other method allow me to focusing and high light the new create row?
You are correct, it cannot be highlighted, because it isn't rendered yet.
But you can use the dispatcher to your advantage there.
private void CommitRow(object sender, DataGridRowEditEndingEventArgs e )
{
//FIRE WHEN ROW IS DONE EDIT
/*
STORING DATA TO DATABASE
*/
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
SelectRowByIndex(Datagrid, Datagrid.Items.Count - 1);
}));
}
This should do the trick. It calls the Dispatcher to do it with a priority thats just after rendering. Visually this should happen instantly.

RowLoaded event - can't modify cell content

During development with Devexpress, we've encountered the use of a InstantFeedbackSource. Using the Row_Loaded, we would like to adjust values of certain rows. Yet the CellContent isn't changed.
Testsolution:
GetQueryable-Method of my datasource:
private void linqInstantFeedbackSource1_GetQueryable_1(object sender, GetQueryableEventArgs e)
{
e.QueryableSource = _testObjects.AsQueryable();
gridView2.RefreshData();
gridControl2.RefreshDataSource();
}
My Row-loaded event
private void gridView2_RowLoaded(object sender, DevExpress.XtraGrid.Views.Base.RowEventArgs e)
gridView2.SetRowCellValue(e.RowHandle, gridView2.Columns["RandomGuid4"], "lalalala");
}
Information:
gridView2.Columns["RandomGuid4"] is not null and refers to the correct-column.
e.RowHandle Refers to the correct Linenumber
Goal:
I want to achieve the following behavior:
At runtime i want to fill the gird with records. When adding the rows i want to check the row for certain values. When a certain value occurs then several another cells should be filled with combobox, hyperlinks,...
The advised way by devexpress is the event CustomCellEdit. But that event is highly unreliable. We're experiencing issues (exceptions from within the control). I've submitted several tickets so far but no response. So we're searching an alternative.
Could someone point out what i'm exactly missing/doing wrong here?
Thank you for your time.
Note: I've tried the use of RefreshData in my RowLoaded-Event but it doesn't appear to be working.

Add and read Multiple textboxes

What is the best way to create and read multiple textboxes in a windows form? In my application, I have a windows form where customer can enter multiple addresses, email addresses
Right now I have a form like this,
TextBoxAddress1 TextBoxEmail1
TextBoxAddress2 TextBoxEmail2
.....
.....
.....
TextBoxAddressN TextBoxEmailN
For this I dragged and dropped multiple controls on a form and named each one of them.
If I use this method I had to write lengthy code to see if first row (TextBoxAddress1 TextBoxEmail1) is filled for validation and even for reading I had to write many lines of code.
Is there a better to way achieve this?
You can use the following code to add a TextBox dynamically to your form:
private int m_CurrTexboxYPos = 10;
private List<TextBox> m_TextBoxList = new List<TextBox>();
private void CreateCheckBox()
{
m_CurrTexboxYPos += 25;
TextBox textbox = new TextBox();
textbox.Location = new System.Drawing.Point(0, m_CurrTexboxYPos);
textbox.Size = new System.Drawing.Size(100,20);
Controls.Add(textbox);
m_TextBoxList.Add(textbox);
}
I would have a listbox/listview with your emails and Add/Edit/Delete buttons which show a popup form - the logic for validating emails, etc. would then be in the one place and your list can grow without you ever needing to add controls to the form.
You could dynamically create textboxes - but you end up writing code to make sure they layout nicely on the form, etc. - having some type of list is easier IMO and also lends itself to binding (e.g. to an email object)
Dynamically adding controls is pretty simple, provided you can use DockStyle and an exclusive container for them (e.g. a Panel). If you can't use DockStyle, then you need to write logic to determine Location and Size (which isn't fun).
On a simple form, I have two buttons and a panel, Button1 adds a new TextBox to Panel1, Button2 iterates through the controls in Panel1 and then checks that they are the correct type or throws an exception. This is where you you would put validation or reading logic. Panel1 needs to have AutoScroll = true; otherwise you will run controls off of the viewable screen.
This concept can be switched for anything that inherits from UserControl (all .Net native controls or your own custom controls).
private void button1_Click(object sender, EventArgs e)
{
TextBox NewEmailBox = new TextBox();
NewEmailBox.Name = "NewEmailBox" + this.panel1.Controls.Count;
NewEmailBox.Dock = DockStyle.Top;
this.panel1.Controls.Add(NewEmailBox);
}
private void button2_Click(object sender, EventArgs e)
{
foreach (Control item in this.panel1.Controls)
{
if (item is TextBox)
{
//Do your reading/validating here.
}
else
{
throw new InvalidCastException(string.Format("{0} was in Panel1 and is of type {1} not TextBox!", item.Name, item.GetType()));
}
}
}
Write a user control for each of the groupings you need. at least one One for address, one for email etc. then all of your validation, calls to your database access is contained in a single location
That is just good design. this way if you have multiple tabs for things like Home Information, Work Information, Emergency Contact Information, you can just place them on the form. This is pretty common for a user profile.
Then a listview for each grouping on a user profile page or whatever, that has edit/delete/add then popup a dialog with the appropriate user control in it.
Most simply, ListBox adove TextBox with Button.
Also you can use DataGridView, BuiltIn functionality for Add\Edit\Delete.
Here using DataGridView (ShowHeader set to false, EditMode to On Enter, with one Column with AutoSizeMode in Fill property)
The less of repeatable code you have, the better programmer you are.
Whenever you see a pattern (something what is repeatable), you could and you should try to optimize it. Unless it's something too small to worry.
In your case, determine first what is the basic of repeatable thing. Do you always have to enter address and email address? Then combine them into a control, which can carry out validation. Do you have to use this control often (or repeat N times)? Then maybe it make sense to switch to a list instead (ListBox, ListView or DataGridView).
Are you too lazy to bother configuring things? Then just optimize something what is obviously going to repeat: put validation into common method and call it from each TextBox event. Or make own TextBox with method build-in. Or do validation at once in the Ok button event by using loop.. or not by using loop.
To find best method you have to first decide best for who. Because customer want something shiny,easy to use, animated, with cats and boobs.. ok, without cats and boobs. The point is: how much work are you willing to put to have it best for the customer.
If I would have to enter table data (or data which form table), I'd go with DataGridView so it would looks like this.. or better:

C# Listview Drag and Drop Rows

I'm trying to implement a C# drag and drop row-reorder with a listview which would then update an SQL database with the current order of the rows. I've come across some snippets of code on the internet (one from this website which implemented a 'var' class) but none seem to be working with my needs. I don't need help updating the database as I have a good idea how I'd do this, but can't seem to get the row reordering to work correctly, any input would be appreciated.
-thanks
m&a
Ensure that AllowDragDrop is set to true.
Implement handlers for at least these 3 events
private void myList_ItemDrag(object sender, ItemDragEventArgs e)
{
DoDragDrop(e.Item, DragDropEffects.Link);
}
private void myList_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Link;
}
private void myList_DragDrop(object sender, DragEventArgs e)
{
// do whatever you need to reorder the list.
}
Getting the index of the row you dropped onto may look something like:
Point cp = myList.PointToClient(new Point(e.X, e.Y));
ListViewItem dragToItem = myList.GetItemAt(cp.X, cp.Y);
int dropIndex = dragToItem.Index;
I know this isn't ListView specific, but I have sample code for implementing row drag and drop out of / into a DataGridView. Some of it is obviously control specific, other code is actually pretty generic (such as deciding when its a drag):
http://adamhouldsworth.blogspot.com/2010/01/datagridview-multiple-row-drag-drop.html
Completely forgot the fact that ListView already allows drag-dropping!
I can also add some theory - when the drop occurs on your control, you will need to hit test on those coordinates (likely a method called HitTest) on the ListView to see what row was hit, this is the basis for where to insert the row being dragged.
Unrelated - is that var class perhaps the new var keyword in C#?

Categories

Resources