# dotNet.ReoGrid 扩展库 - 创建自定义下拉单元格

ReoGrid 提供了[单元格主体(Cell Body)](../cell/custom-cell/ "自定义单元格".html)功能，这是一种创建自定义单元格类型的方式。其中内置了一种名为`DropdownCell`的单元格主体类型，可以创建用户友好的自定义下拉单元格。了解更多关于[内置单元格类型](../cell/built-in-cell-types.html)的内容。

要创建自定义下拉单元格，需要从`DropdownCell`类继承创建自己的类，该类位于`unvell.ReoGrid.CellTypes`命名空间中。

## 下拉界面

`DropdownCell`类提供了创建用户自定义下拉单元格的最简单方式，它会在单元格右侧显示一个箭头按钮，并接收用户操作来显示和隐藏下拉面板。

![下拉单元格示意图](../images/186.png)

使用`DropdownCell`类只需做以下两件事：
* 将任意控件放入下拉面板中
* 将控件中的选中项设置为单元格的数据

`DropdownCell`提供了一个名为`DropdownControl`的属性，用于指定显示在下拉面板中的控件。

## 创建下拉 ListView

这个示例展示如何创建一个显示标准.NET ListView控件的下拉单元格。创建一个名为`ListViewDropdownCell`的类，让它继承自`DropdownCell`类。

```aardio
// 在aardio中创建ListView下拉单元格
import dotNet.ReoGrid;
import System.Windows.Forms;

// 定义ListView下拉单元格类
class ListViewDropdownCell {
    ctor() {
        // 初始化ListView
        this.listView = System.Windows.Forms.ListView();
        this.listView.BorderStyle = System.Windows.Forms.BorderStyle.None;
        this.listView.View = System.Windows.Forms.View.Details;
        this.listView.FullRowSelect = true;

        // 将ListView设置为下拉控件
        this.DropdownControl = this.listView;
    }
}
```

在aardio中，可以通过以下代码将这个`ListViewDropdownCell`实例添加到ReoGrid工作表中：

```aardio
// 将自定义下拉单元格添加到B2单元格
sheet1["B2"] = ListViewDropdownCell();
```

也可以通过设置单元格的`Body`属性来更改单元格主体对象。将`Body`属性设为`null`会从单元格中移除单元格主体。

运行程序并点击下拉按钮，会显示一个包含`ListView`控件的空面板。

![空下拉面板](../images/187.png)

要在列表视图中显示选项，使用以下代码添加项目：

```aardio
// 添加列表视图列
listView.Columns.Add("列1", 120);
listView.Columns.Add("列2", 120);

// 添加分组和项目
var group1 = listView.Groups.Add("grp1", "分组1");
listView.Items.Add(ListViewItem(["项目1.1", "子项1.1"]) { Group = group1 });
listView.Items.Add(ListViewItem(["项目1.2", "子项1.2"]) { Group = group1 });
listView.Items.Add(ListViewItem(["项目1.3", "子项1.3"]) { Group = group1 });

var group2 = listView.Groups.Add("grp2", "分组2");
listView.Items.Add(ListViewItem(["项目2.1", "子项2.1"]) { Group = group2 });
listView.Items.Add(ListViewItem(["项目2.2", "子项2.2"]) { Group = group2 });
listView.Items.Add(ListViewItem(["项目2.3", "子项2.3"]) { Group = group2 });
```

再次运行程序：
![带项目的下拉面板](../images/188.png)

可以看到带有模拟项目的`ListView`控件已经显示，但下拉面板的宽度太小。要解决这个问题，可以设置`DropdownCell`实例的`MinimumDropdownWidth`属性：

```aardio
// 扩大下拉面板
this.MinimumDropdownWidth = 300;
```

![调整宽度后的下拉面板](../images/189.png)

## 接收选中项

通过处理列表视图的`Click`事件来设置选中项：

```aardio
// 添加点击事件处理程序
this.listView.Click = function(sender, e) {
    if(this.listView.SelectedItems.Count > 0) {
        // 将第一个选中项设为单元格数据
        this.Cell.Data = this.listView.SelectedItems[0].Text;
        this.PullUp();  // 收起下拉面板完成编辑
    }
}
```

运行程序，尝试从下拉列表中选择项目，选中项会显示在单元格内。

![选中项目后的单元格](../images/190.png)

最后，为下拉单元格设置边框和初始文本：

```aardio
sheet1["B2"] = "请选择...";
sheet1["B2"] = ListViewDropdownCell();
sheet1.Ranges["B2"].BorderOutline = ReoGrid.Graphics.SolidColor.Gray;
```

## 最终效果

编辑前：
![编辑前状态](../images/192.png)

选择项目：
![选择项目状态](../images/193.png)

编辑后：
![编辑后状态](../images/194.png)

完整的源代码和演示程序包含在发布包的演示项目中，可以从下载页面获取。

## 下拉单元格中的电子表格

如果您考虑实现一个允许最终用户从另一个子电子表格中选择内容的功能，也可以考虑将另一个ReoGrid实例放入下拉面板中。