数据绑定到未知类型的容器

时间:2012-05-02 15:02:42

标签: java jface eclipse-emf emf eclipse-databinding

我有一个以下类型的简单EMF模型:

EClass FooGroup {
    EString name;
    @Properties(containment=true, upper=-1)
    List<Node> nodes;
}
EClass BarGroup {
    EString name;
    @Properties(containment=true, upper=-1)
    List<Node> nodes;
}
EClass Node {
    EString name;
}

我想在一个简单的TableViewer中显示节点的所有名称,以及它们的父组的名称。不幸的是,eContainer()是一项操作,而不是一项功能。这意味着我无法使用JFace Databinding框架将此属性链接到GUI。

我该如何解决这个问题?我是否创建了衍生功能?有什么技巧吗?

4 个答案:

答案 0 :(得分:3)

我想不出在EMF数据绑定中使用eContainer的方法,但是将指定的父引用添加到节点并在eContainer更改时以编程方式更新它并不困难。 / p>

另一种解决方案是添加父项,然后更改生成的代码:

/*
 * @generated NOT
 */
public Group getParent() {
    if (eContainer() instanceof Group) {
        return (Group) eContainer();
    }
    return null;
}

然后您可以使用FeaturePath来获取EMFProperty,如下所示:

    IEMFProperty groupNameProperty = EMFProperties.value(
      FeaturePath.fromList(
        ModelPackage.Literals.NODE__PARENT,
        ModelPackage.Literals.GROUP__NAME
      )
    );

答案 1 :(得分:1)

如果您永远不需要将节点从其中一个容器移动到另一个容器,并且您从不将不同包含的节点混合在一起,那么您可以使用以下解决方案。

这个想法是为节点创建子类,为存储它们的每个位置创建一个子类。然后子类可以有一个普通的容器引用。

编辑:更仔细地阅读您的问题我发现您必须能够统一对待这些对象,并且这种情况不起作用。但也许我的third solution会!

无论如何,我会在这里留下这个答案。也许它会对其他人有用。

class FooGroup {
    String name
    contains FooNode[] nodes opposite group
}

class BarGroup {
    String name
    contains BarNode[] nodes opposite group
}

class Node {
    String name
}

class BarNode extends Node {
    container BarGroup group opposite nodes
}

class FooNode extends Node {
    container FooGroup group opposite nodes
}

答案 2 :(得分:0)

有一种标准的方法可以做到这一点:

在子对象中为父对象创建一个引用,并为其设置适当的oppositecontainer属性。

通过这种方式,类之间的关系在模型中很明显,并且会自动维护,因此您不必编写任何自定义代码。

以下是Xcore中的一个示例:

class Master {
    contains Slave[] slaves opposite master
}

class Slave {
    container Master master opposite slaves
}

为什么不在Ecore中也有同样的东西,而我们在这里:

<eClassifiers xsi:type="ecore:EClass" name="Master">
  <eStructuralFeatures xsi:type="ecore:EReference" name="slaves" eType="#//Slave"
      containment="true" eOpposite="#//Slave/master"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Slave">
  <eStructuralFeatures xsi:type="ecore:EReference" name="master" eType="#//Master"
      eOpposite="#//Master/slaves"/>
</eClassifiers>

答案 3 :(得分:0)

可以创建解决此问题的自定义容器属性类。

通过这种方式,您无需修改​​模型类以便能够绑定到容器。新属性对所有电子对象都有用。

public static IValueProperty containerProperty() {
    return new ContainerProperty();
}

public class ContainerProperty extends ValueProperty {
    @Override
    public IObservableValue observe(Realm realm, Object source) {
        return Observables.constantObservableValue(realm, 
            source == null ? null : ((EObject) source).eContainer(), 
            getValueType());
    }

    @Override
    protected Object doGetValue(Object source) {
        return ((EObject) source).eContainer();
    }

    @Override
    public Object getValueType() {
        return EObject.class;
    }
};

使用示例:

IObservableValue obs = containerProperty().observeDetail(node);

此课程不会收听容器的更改。但我认为有可能实现这样的财产。也许使用SimpleValueProperty类是适合的。