Windows窗体DataGridView中的手风琴 [英] Accordion in Windows Forms DataGridView

查看:288
本文介绍了Windows窗体DataGridView中的手风琴的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在Windows Form DataGridView中实现某种手风琴效果。当用户选择一行时,该行被展开以显示一些更多的信息,并且如果可能的话一些按钮或其他控件。问题是,我绝对不知道如何做到这一点。我试图搜索网络,但是我发现没有什么可以引导我在创建这个方向正确的方向。我希望有人能告诉我怎么做? (不一定是代码示例)



我创建了下面的模型来显示我想做什么。



我想到调整列高度并覆盖OnPaint方法。我只需要在第一个版本中显示一些文本。如果这样做可能会很好。我知道,在将来我需要放置一些按钮或其他控件来做所选项目的各种事情。如果这是非常复杂的,我现在将跳过这一部分。我知道我可以使用工具提示文本和按钮列等,但在我的情况下,我需要做手风琴。





最好的问候
Hans Milling ...

解决方案

这不是很难做到。最好的方法是创建一个专用的 UserControl 并将其重叠在正确的位置。



为了腾出空间它只是改变行的高度,跟踪行,所以你可以在它失去选择时恢复。



您还必须决定是否可以扩展多行,以及用户应该做什么来展开和重置行。



UserControl 可以有一个函数 displayRowData(DataGridViewRow row),您可以将其中的感兴趣的字段称为标签等..



您还应该有一个关于 Buttons 将与 DataGridView ..交互。



如果您只想在一个时间,您可以在前面创建 UC ,使 DGV 并隐藏它。稍后用户交互,如点击行,或某个单元格,您可以将其移动到正确的行并显示。



如果多行可以要扩展,您将需要创建几个 UC ,并在列表中跟踪它们。



这是一个最小的例子来鼓励你..:



  int normalRowHeight = -1; 
UcRowDisplay display = new UcRowDisplay();
DataGridViewRow selectedRow = null;

public Form1()
{
InitializeComponent();

//创建一个显示对象
display = new UcRowDisplay();
display.Visible = false;
display.Parent = DGV;
display.button1Action = someAction;
}

填写DGV后

  //存储正常行高度
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;
}
//假定multiselect = false
selectedRow = DGV.SelectedRows [0];
//假设ColumnHeader显示与行的高度相同
int y =(selectedRow.Index + 1)* normalRowHeight;
display.Location = new Point(1,y);
//填写DGV的整个宽度。
//也许你需要更多,如果DGV横向滚动
//或更小,如果你显示一个垂直滚动条..
display.Width = DGV.ClientSize.Width;
//为显示对象腾出空间
selectedRow.Height = display.Height;
//告诉它显示我们的行数据
display.displayRowData(selectedRow);
//显示
display.Show();
}

private void DGV_ColumnWidthChanged(object sender,DataGridViewColumnEventArgs e)
{
//强制刷新显示
display.Refresh();
}

这是由显示对象中按钮触发的测试动作: p>

  public void someAction(DataGridViewRow row)
{
Console.WriteLine(row.Index ++ row .Cells [2] .Value.ToString());
}

当然,您需要一个UserControl。这是一个简单的,有两个标签,一个按钮和一个额外的标签来关闭显示:

  public partial class UcRowDisplay: UserControl 
{
public UcRowDisplay()
{
InitializeComponent();
}

public delegate void someActionDelegate(DataGridViewRow row);
public someActionDelegate button1Action {get;组; }
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();
}


}

它包含tthree 标签按钮。在设计器中,它看起来像这样:





请注意,为了让我更容易一些,我已将DGV修改为




  • 没有RowHeader;

  • 假定列标题与行的高度相同。

  • 所有(正常)行要具有相同的高度。

  • 将DGV设置为multiselect = false和只读


I need to implement some kind of accordion effect in a Windows Form DataGridView. When the user selects a row, the row is expanded to display some more information and if possible some buttons or other controls. The problem is, I have absolutely no clue, how to do this. I tried to search the web, but I found nothing that can lead me in the right direction in creating this. I hope someone can tell me how to do this? (does not have to be a code sample)

I created the below mockup to display what I want to do.

I thought about adjusting the columns height and override the OnPaint method. I only need to display some text in the first version. If that is possible that would be great. I know that in the future I would need to place some buttons or other controls to do various things with the selected item. If that is very complicated to achieve, I will skip that part for now. I know I could use tooltips for text and have button columns etc. but in my case, I need to do it as an accordion.

Best regards Hans Milling…

解决方案

This is not really hard to do. The best approach would be to create a dedicated UserControl and overlay it at the right spot.

To make room for it simply change the Row's Height, keeping track of the row, so you can revert it when it looses selection.

You will also have to decide if more than one row can be expanded and just what the user is supposed to do to expand and to reset the row..

The UserControl could have a function displayRowData(DataGridViewRow row) which you could call the display the fields you are interested in in its Labels etc..

You should also have a plan on how the Buttons shall interact with the DataGridView..

If you only want one Row to be expanded at a time, you can create the UC up front, make the DGV its Parent and hide it. Later upon the user interaction, like clicking at the row, or a certain cell you would move it to the right row and show it..

If more than one row can be expanded you will need to create several UCs and keep track of them in a List..

Here is a minimal example to encourage you..:

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;
}

After you have filled the DGV

    // store the normal row height
    normalRowHeight = DGV.Rows[0].Height;

You need at least these events:

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();
}

Here is a test action triggered by the button in the display object:

public void someAction(DataGridViewRow row)
{
    Console.WriteLine(row.Index + "  " + row.Cells[2].Value.ToString());
}

And of course you need a UserControl. Here is a simple one, with two Labels, one Button and one extra Label to close the display:

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();
    } 


}

It contains tthree Labels and a Button. In the Designer it looks like this:

Note that in order to make it a little easier on me I have modified the DGV to

  • have no RowHeader; modify the location if you have one.
  • assumed the column header to have the same height as a row.
  • all (normal) rows to have the same height.
  • set the DGV to multiselect=false and read-only

这篇关于Windows窗体DataGridView中的手风琴的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆