# 选择图元

介绍

Revit 开发过程中,用户操作鼠标在文档中选择对象是我们最常用的交互方式之一。

我们可以通过提示让用户选择目标对象,并在程序中对用户成功选择的对象进行处理,或者读取对应的信息,以达到我们程序的目的。

选择对象的方式有很多种,包括:

  • 单选
  • 多选
  • 框选

# 单选对象

用户通过鼠标点选的形式进行交互;

//提示用户选择对象
SelectionResult<Reference> result = uiDocument.SelectObject(
    Autodesk.Revit.UI.Selection.ObjectType.Face ,
    prompt : "请选择一个要操作面");
if(result.SelectionStatus == SelectionStatus.Succeeded)
{
    Reference reference = result.Value;
}

单选对象的时候,提供了对对象进行预过滤的能力,避免用户选到非预期的对象,比如下面这个例子可以过滤出链接文档中的面进行选择:

SelectionResult<Reference> result = uiDocument.SelectObject(
    Autodesk.Revit.UI.Selection.ObjectType.LinkedElement,
    referencePredicate: parameters => parameters.Reference?.ConvertToStableRepresentation(document).Contains("SURFACE"),
    prompt:"请选择链接的项目中一个要操作面");

if(result.SelectionStatus == SelectionStatus.Succeeded)
{
    Reference reference = result.Value;
}

又或者是过滤出链接文档中的墙体:

SelectionResult<Reference> result = uiDocument.SelectObject(
    Autodesk.Revit.UI.Selection.ObjectType.LinkedElement,
    element=>element.Category.Id== BuiltInCategories.Wall
    prompt:"请选择链接的项目中一个要操作面");

if(result.SelectionStatus == SelectionStatus.Succeeded)
{
    Reference reference = result.Value;
}

如果选择的对象是图元,可以选择以下的方式

//提示用户选择图元
Element element = uiDocument.SelectElement("请选择一个要操作的图元");

//提示公户选择某个类别的图元
Element element = uiDocument.SelectElement(BuiltinCategory.OST_Walls , "请选择一个要操作的图元");

//较为复杂的过滤条件,也可以通过回调函数进行过滤
Element element = uiDocument.SelectElement(
    (element) => element is FamilyInstan instance && instance.Name = "Test" ,
    "请选择一个要操作的图元");

# 多选对象

用户通过鼠标多选的形式进行交互,并在结束后点击完成按钮;

SelectionResult<IList<Reference>> result = uiDocument.SelectObjects(Autodesk.Revit.UI.Selection.ObjectType.Face);
if(result.SelectionStatus == SelectionStatus.Succeeded)
{
    IList<Reference> references = result.Value;
}

同单选一样,多选也提供了直接选择图元的方法:

SelectionResult<IList<Element>> result = uiDocument.SelectElements(BuiltinCategory.OST_Walls);
if(result.SelectionStatus == SelectionStatus.Succeeded)
{
    IList<Element> references = result.Value;
}

# 框选图元

用户通过鼠标框选的形式进行交互;

SelectionResult<IList<Element>> result = uiDocument.SelectElementsByRectangle(BuiltinCategory.OST_Walls);
if(result.SelectionStatus == SelectionStatus.Succeeded)
{
    IList<Element> elements = result.Value;
}

# 选择点

除了上面介绍的几种获取对象的方式外,API 还单独提供了一个获取点的方法

SelectionResult<XYZ> result = uiDocument.SelectPoint("请选择一个点");
if(result.SelectionStatus == SelectionStatus.Succeeded)
{
    XYZ point = result.Value;
}

# 返回值

扩展包对选择后的结果进行封装,统一返回值为 SectionResult<T> 的泛型;

public class SelectionResult<T>
{
    /// <summary>
    /// message
    /// </summary>
    public string Message { get; set; }

    /// <summary>
    /// result
    /// </summary>
    public T Value { get; }

    /// <summary>
    /// selction state
    /// </summary>
    public SelectionStatus SelectionStatus { get; set; }

    /// <summary>
    /// exception
    /// </summary>
    public Exception Exception { get; set; }

    /// <summary>
    /// Has exception
    /// </summary>
    public bool HasException  { get; }
}

用户的选择操作有三种状态:

如果成功

则返回值的属性 SelectionStatus 将为 SelectionStatus.Succeeded ;

如果用户取消选择(如按下 ESC)

则返回值的属性 SelectionStatus 将为 SelectionStatus.Cancelled ;

如果失败

则返回值的属性 SelectionStatus 将为 SelectionStatus.Failed ;