我有一个以下类型的简单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。
我该如何解决这个问题?我是否创建了衍生功能?有什么技巧吗?
答案 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)
有一种标准的方法可以做到这一点:
在子对象中为父对象创建一个引用,并为其设置适当的opposite
和container
属性。
通过这种方式,类之间的关系在模型中很明显,并且会自动维护,因此您不必编写任何自定义代码。
以下是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
类是适合的。