问题
I have a form with a DataGridView on it. I select a row (always a single row) of data. After I click a button I would like to open a new form and always position it directly under the selected row. How should I do this?
In my button click I do something like this:
private void myBtn_Click(object sender, EventArgs e)
{
if (myDGV.SelectedCells.Count > 0)
{
int i = myDGV.SelectedCells[0].RowIndex;
DataGridViewRow r = myDGV.Rows[i];
// READ SOME DATA FROM THE ROW
newForm form = new newForm();
//POPULATE THE NEW FORM WITH DATA
form.ShowDialog(this); //POSITION OF THIS FORM SHOULD BE DIRECTLY UNDER SELECTED ROW
}
}
回答1:
You can use DataGridView.GetRowDisplayRectangle to obtain the row rectangle in data grid view client coordinates, then Control.RectangleToScreen to convert them to a screen coordinates needed for determining the new form location, like this:
private void myBtn_Click(object sender, EventArgs e)
{
if (myDGV.SelectedCells.Count > 0)
{
int i = myDGV.SelectedCells[0].RowIndex;
DataGridViewRow r = myDGV.Rows[i];
// READ SOME DATA FROM THE ROW
newForm form = new newForm();
//POPULATE THE NEW FORM WITH DATA ...
// Position the form under the selected row
form.StartPosition = FormStartPosition.Manual;
var rect = myDGV.RectangleToScreen(myDGV.GetRowDisplayRectangle(i, false));
form.Location = new Point(rect.Left, rect.Bottom);
form.ShowDialog(this);
}
}
回答2:
While Ivans solution is 100% valid and correct, there are some minor "gripes" with it as far as aesthetics are concerned (which he could easily cater for in his elegant solution). If you want the dialog box to appear directly underneath the row, flush with both the left side of the gridview and the row bottom, you need to do it differently - the long way.
I reiterate this - Ivans solution is very appropriate and much cleaner.. The below solution gives you a little more freedom concerning form placement and alike. I threw this together in a few minutes so sorry if I missed something small.
You can always use the built in properties like Rectangle.Bottom
and alike. I did this to, I guess, show the math on how to approach things.
private void myBtn_Click(object sender, EventArgs e)
{
if(dataGridView1.SelectedRows.Count > 0)
{
var rowIndex = myDGV.SelectedRows[0].Index;
var row = myDGV.Rows[rowIndex];
var formLocation = this.Location; //Form location
var gridLocation = myDGV.Location; //grid location
var rowLocation = myDGV.GetRowDisplayRectangle(rowIndex, false).Location; //row location
newForm form = new newForm();
form.StartPosition = FormStartPosition.Manual; //set to manual
//form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
//form.BackColor = Color.Blue;
form.Location = GetPopupStartingLocation(
new Point[]
{
formLocation,
gridLocation,
rowLocation
},
row.Height);
form.Show(this);
}
}
/*
A small helper method - didn't need to put this in a method
but I did it for clarity.
*/
private Point GetPopupStartingLocation(Point[] locations, int rowHeight)
{
var yPadding = 5;
var xValues = locations.Sum(x => x.X);
var yValues = locations.Sum(x => x.Y) + ((rowHeight * 2) + yPadding);
return new Point(xValues, yValues);
}
Now Most of this is pretty much the same as Ivan's except the "longer route" but this gives you a little more control over your location using the helper function. You can add/remove adjust the values down there and find something you like. Works fine.
Hope this helps.
+1 to Ivan for the clean solution.
来源:https://stackoverflow.com/questions/35684387/winforms-position-new-form-directly-under-datagridview-selected-row-of-parent