如何在创建组件时以编程方式设置视图模型 Class
How to Set View Model Class Programmatically when Creating Components
我正在试验 ZK 框架,并寻找通过实用程序以编程方式加载 zul 定义的视图的方法 class,该实用程序使用执行以编程方式加载视图定义。
但是我确实找不到以编程方式设置视图模型 class 的方法,这将非常方便,并且允许使用一些非常简单的方法重用具有不同视图模型的视图 class es.
即加载视图的代码如下所示:
public static Component loadComponent(Class<?> modelClz, String zulFile, Component parent, Map<String,Object> params) {
Execution exec = Executions.getCurrent();
PageDefinition page = exec.getPageDefinitionDirectly(
new InputStreamReader(modelClz.getResourceAsStream(zulFile)),
null
);
return exec.createComponents(
page,
// no (previous parent)
parent,
params
);
}
我考虑过通过在页面定义的顶部组件信息上以编程方式设置注释来“强制”视图模型,如下所示:
public static Component loadComponent(Class<?> modelClz, String zulFile, Component parent, Map<String,Object> params) {
Execution exec = Executions.getCurrent();
PageDefinition page = exec.getPageDefinitionDirectly(
new InputStreamReader(modelClz.getResourceAsStream(zulFile)),
null
);
if (!page.getChildren().isEmpty()) {
ComponentInfo top = (ComponentInfo) page.getChildren().get(0);
AnnotationMap annotationMap = top.getAnnotationMap();
String viewModel = "viewModel";
if (annotationMap==null || !annotationMap.getAnnotatedProperties().contains(viewModel)) {
// no view model set on top declaration,
// force ours
Map<String,String[]> id = new HashMap<>();
id.put(null, new String[]{"vm"});
top.addAnnotation("viewModel","id",id, null);
Map<String,String[]> init = new HashMap<>();
init.put(null, new String[]{String.format("%s", modelClz.getName())});
top.addAnnotation("viewModel","init",init, null);
top.enableBindingAnnotation();
}
}
return exec.createComponents(
page,
// no (previous parent)
parent,
params
);
}
但是这没有用。也许在这个过程中为时已晚。或者有一些非常简单的方法可以做到这一点,但我错过了。或者也许我应该“应用”一些 BindComposer,但我不确定该怎么做。
任何有用的想法都会很棒!
只是为了确保我已经理解:
- 您有一些 zul 片段(例如可重复使用的 UI 结构)
- 此片段使用 MVVM 模式,但您想在实例化该片段时选择一个 viewModel 对象,而不是在 zul viewModel="@id()@init( )”属性
- 您想从可以访问 UI 的 java class 初始化该片段(使用 Execution#createComponents 加载片段并将它们附加到页面)
听起来正确吗?
如果是这样的话,你可以让这个方法更简单
属性可以写成viewModel="@id('yourVmId')@init(aReferenceToAnAlreadyInstantiatedObject)"
.
此处重要说明:请注意,我没有在@init 声明中将对象放在引号中。我正在传递一个实际对象,而不是包含对要实例化的 class 的引用的字符串。
当您调用 execution.createComponents() 时,您可以将参数的 map 传递给创建的页面。然后,您可以在创建绑定 VM 时使用相关传递对象的名称。
看看这个fiddle(有点粗糙,但应该有道理):https://zkfiddle.org/sample/2jij246/4-Passing-an-object-through-createComponents-as-VM#source-2
HashMap<String, Object> args = new HashMap<String, Object>();
args.put("passedViewModel", new GenericVmClass("some value in the passed VM here"));
Executions.createComponents("./fragment.zul", e.getTarget().getPage(),null, args);
仅供参考,如果您使用的是 ZK shadow-elements,您还可以将该对象从带有纯 MVVM 模式源的应用程序传递到片段。
例如,<apply>
shadow 元素可以使用变量名将对象传递给创建的内容,您可以在初始化 VM 时使用该变量名。
关于 BindComposer:
最多需要实例化 BindComposer 到 ZK 7.X
在 ZK 8.X 及更高版本中,当您在 ZK 组件上使用 viewModel="..." 属性时,BindComposer 将自动实例化。
我正在试验 ZK 框架,并寻找通过实用程序以编程方式加载 zul 定义的视图的方法 class,该实用程序使用执行以编程方式加载视图定义。
但是我确实找不到以编程方式设置视图模型 class 的方法,这将非常方便,并且允许使用一些非常简单的方法重用具有不同视图模型的视图 class es.
即加载视图的代码如下所示:
public static Component loadComponent(Class<?> modelClz, String zulFile, Component parent, Map<String,Object> params) {
Execution exec = Executions.getCurrent();
PageDefinition page = exec.getPageDefinitionDirectly(
new InputStreamReader(modelClz.getResourceAsStream(zulFile)),
null
);
return exec.createComponents(
page,
// no (previous parent)
parent,
params
);
}
我考虑过通过在页面定义的顶部组件信息上以编程方式设置注释来“强制”视图模型,如下所示:
public static Component loadComponent(Class<?> modelClz, String zulFile, Component parent, Map<String,Object> params) {
Execution exec = Executions.getCurrent();
PageDefinition page = exec.getPageDefinitionDirectly(
new InputStreamReader(modelClz.getResourceAsStream(zulFile)),
null
);
if (!page.getChildren().isEmpty()) {
ComponentInfo top = (ComponentInfo) page.getChildren().get(0);
AnnotationMap annotationMap = top.getAnnotationMap();
String viewModel = "viewModel";
if (annotationMap==null || !annotationMap.getAnnotatedProperties().contains(viewModel)) {
// no view model set on top declaration,
// force ours
Map<String,String[]> id = new HashMap<>();
id.put(null, new String[]{"vm"});
top.addAnnotation("viewModel","id",id, null);
Map<String,String[]> init = new HashMap<>();
init.put(null, new String[]{String.format("%s", modelClz.getName())});
top.addAnnotation("viewModel","init",init, null);
top.enableBindingAnnotation();
}
}
return exec.createComponents(
page,
// no (previous parent)
parent,
params
);
}
但是这没有用。也许在这个过程中为时已晚。或者有一些非常简单的方法可以做到这一点,但我错过了。或者也许我应该“应用”一些 BindComposer,但我不确定该怎么做。
任何有用的想法都会很棒!
只是为了确保我已经理解:
- 您有一些 zul 片段(例如可重复使用的 UI 结构)
- 此片段使用 MVVM 模式,但您想在实例化该片段时选择一个 viewModel 对象,而不是在 zul viewModel="@id()@init( )”属性
- 您想从可以访问 UI 的 java class 初始化该片段(使用 Execution#createComponents 加载片段并将它们附加到页面)
听起来正确吗?
如果是这样的话,你可以让这个方法更简单
属性可以写成viewModel="@id('yourVmId')@init(aReferenceToAnAlreadyInstantiatedObject)"
.
此处重要说明:请注意,我没有在@init 声明中将对象放在引号中。我正在传递一个实际对象,而不是包含对要实例化的 class 的引用的字符串。
当您调用 execution.createComponents() 时,您可以将参数的 map
看看这个fiddle(有点粗糙,但应该有道理):https://zkfiddle.org/sample/2jij246/4-Passing-an-object-through-createComponents-as-VM#source-2
HashMap<String, Object> args = new HashMap<String, Object>();
args.put("passedViewModel", new GenericVmClass("some value in the passed VM here"));
Executions.createComponents("./fragment.zul", e.getTarget().getPage(),null, args);
仅供参考,如果您使用的是 ZK shadow-elements,您还可以将该对象从带有纯 MVVM 模式源的应用程序传递到片段。
例如,<apply>
shadow 元素可以使用变量名将对象传递给创建的内容,您可以在初始化 VM 时使用该变量名。
关于 BindComposer: 最多需要实例化 BindComposer 到 ZK 7.X
在 ZK 8.X 及更高版本中,当您在 ZK 组件上使用 viewModel="..." 属性时,BindComposer 将自动实例化。