C# Windows窗体DataGridView中的手风琴
我需要在Windows窗体DataGridView中实现某种手风琴效果。当用户选择一行时,该行将展开以显示更多信息,如果可能,还会显示一些按钮或其他控件。问题是,我完全不知道该怎么做。我试图搜索网络,但我发现没有任何东西可以引导我朝着正确的方向创建这个。我希望有人能告诉我怎么做?(不必是代码示例) 我创建了下面的模型来显示我想要做什么 我考虑过调整列的高度并重写OnPaint方法。我只需要在第一个版本中显示一些文本。如果可能的话,那就太好了。我知道在将来,我需要放置一些按钮或其他控件来对所选项目执行各种操作。如果要实现这一点非常复杂,我现在将跳过这一部分。我知道我可以使用工具提示来显示文本和按钮栏等,但在我的情况下,我需要像手风琴一样来做 致意C# Windows窗体DataGridView中的手风琴,c#,windows,forms,datagridview,accordion,C#,Windows,Forms,Datagridview,Accordion,我需要在Windows窗体DataGridView中实现某种手风琴效果。当用户选择一行时,该行将展开以显示更多信息,如果可能,还会显示一些按钮或其他控件。问题是,我完全不知道该怎么做。我试图搜索网络,但我发现没有任何东西可以引导我朝着正确的方向创建这个。我希望有人能告诉我怎么做?(不必是代码示例) 我创建了下面的模型来显示我想要做什么 我考虑过调整列的高度并重写OnPaint方法。我只需要在第一个版本中显示一些文本。如果可能的话,那就太好了。我知道在将来,我需要放置一些按钮或其他控件来对所选项目
Hans Milling…这其实并不难做到。最好的方法是创建一个专用的
UserControl
,并将其覆盖在正确的位置
要为它腾出空间,只需更改行的高度
,跟踪该行,以便在它失去选择时可以将其还原
您还必须决定是否可以扩展多行,以及用户应该如何扩展和重置行
UserControl
可以有一个函数displayRowData(DataGridViewRow)
,您可以调用该函数来显示您对其标签感兴趣的字段
等
您还应该计划按钮
如何与DataGridView
交互
如果您一次只想扩展一行,可以预先创建UC
,将DGV
设为其父项并将其隐藏。稍后在用户交互时,如单击行或某个单元格,您会将其移动到右行并显示
如果可以展开多行,则需要创建多个UCs
,并在列表中跟踪它们
下面是一个最简单的例子来鼓励您:
int normalRowHeight = -1;
UcRowDisplay display = new UcRowDisplay();
DataGridViewRow selectedRow = null;
public Form1()
{
InitializeComponent();
// create one display object
display = new UcRowDisplay();
display.Visible = false;
display.Parent = DGV;
display.button1Action = someAction;
}
填充DGV后
// store the normal row height
normalRowHeight = DGV.Rows[0].Height;
您至少需要以下事件:
private void DGV_SelectionChanged(object sender, EventArgs e)
{
if (selectedRow != null) selectedRow.Height = normalRowHeight;
if (DGV.SelectedRows.Count <= 0)
{
selectedRow = null;
display.Hide();
return;
}
// assuming multiselect = false
selectedRow = DGV.SelectedRows[0];
// assuming ColumnHeader show with the same height as the rows
int y = (selectedRow.Index + 1) * normalRowHeight;
display.Location = new Point(1, y);
// filling out the whole width of the DGV.
// maybe you need more, if the DGV is scrolling horizontally
// or less if you show a vertical scrollbar..
display.Width = DGV.ClientSize.Width;
// make room for the display object
selectedRow.Height = display.Height;
// tell it to display our row data
display.displayRowData(selectedRow);
// show the display
display.Show();
}
private void DGV_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
{
// enforce refresh on the display
display.Refresh();
}
当然,你需要一个用户控件。这是一个简单的,有两个标签,一个按钮和一个额外的标签来关闭显示器:
public partial class UcRowDisplay : UserControl
{
public UcRowDisplay()
{
InitializeComponent();
}
public delegate void someActionDelegate(DataGridViewRow row);
public someActionDelegate button1Action { get; set; }
DataGridViewRow myRow = null;
public void displayRowData(DataGridViewRow row)
{
myRow = row;
label1.Text = row.Cells[1].Value.ToString();
label2.Text = row.Cells[0].Value.ToString();
rowDisplayBtn1.Text = row.Cells[2].Value.ToString();
}
private void rowDisplayBtn1_Click(object sender, EventArgs e)
{
button1Action(myRow);
}
private void label_X_Click(object sender, EventArgs e)
{
myRow.Selected = false;
this.Hide();
}
}
它包含三个标签
和一个按钮
。在设计器中,它如下所示:
请注意,为了让我更轻松,我将DGV修改为
- 没有行标题;修改位置(如果有)
- 假定列标题与行具有相同的高度
- 所有(正常)行具有相同的高度
- 将DGV设置为multiselect=false且为只读
更新
下面是一个快速滚动示例:
private void DGV_Scroll(object sender, ScrollEventArgs e)
{
DGV.PerformLayout();
var ccr = DGV.GetCellDisplayRectangle(0, selectedRow.Index, true);
display.Top = ccr.Top + normalRowHeight; // **
display.Visible = (ccr.Top >= 0 && ccr.Height > 0);
}
该(**)假设所选行保持可见。SelectionChanged事件中应进行相同的计算!当水平滚动发生时,由您决定应该发生什么
请注意,在当前行之前添加或删除行时,需要进行类似的更新。因此,它应该被移动到一个你在这些情况下调用的函数。看看我更新了答案,包含了按钮操作的代码。非常感谢。这正是我需要开始的。顺便说一句,我只是注意到你的模型显示了扩展行以及扩展区域。为此,您必须1)使行更高,2)计算uc以显示更低的值3)确保行单元格将其内容与顶部对齐。。
private void DGV_Scroll(object sender, ScrollEventArgs e)
{
DGV.PerformLayout();
var ccr = DGV.GetCellDisplayRectangle(0, selectedRow.Index, true);
display.Top = ccr.Top + normalRowHeight; // **
display.Visible = (ccr.Top >= 0 && ccr.Height > 0);
}