Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Windows窗体DataGridView中的手风琴_C#_Windows_Forms_Datagridview_Accordion - Fatal编程技术网

C# Windows窗体DataGridView中的手风琴

C# Windows窗体DataGridView中的手风琴,c#,windows,forms,datagridview,accordion,C#,Windows,Forms,Datagridview,Accordion,我需要在Windows窗体DataGridView中实现某种手风琴效果。当用户选择一行时,该行将展开以显示更多信息,如果可能,还会显示一些按钮或其他控件。问题是,我完全不知道该怎么做。我试图搜索网络,但我发现没有任何东西可以引导我朝着正确的方向创建这个。我希望有人能告诉我怎么做?(不必是代码示例) 我创建了下面的模型来显示我想要做什么 我考虑过调整列的高度并重写OnPaint方法。我只需要在第一个版本中显示一些文本。如果可能的话,那就太好了。我知道在将来,我需要放置一些按钮或其他控件来对所选项目

我需要在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);
}