Mvvm 如何在模板中显示弹出窗口并将其传递给参数

Mvvm 如何在模板中显示弹出窗口并将其传递给参数,mvvm,zk,Mvvm,Zk,我的应用程序的一部分是记录比赛的完成时间。由于这很可能是在手机或平板电脑上完成的,我想实现一个小弹出窗口,以便轻松修改时间,而无需精确设置焦点并键入时间。但是,将每个完成时间的开始时间设置为00:00:00将使过程非常困难,因此我希望将其初始化为最后输入的完成时间。如果输入的时间在网格的顶部,我希望弹出窗口直接显示在时间框的下方;如果输入的时间在网格的底部,则弹出窗口显示在时间框的上方。下面是我的代码的精简版本,希望有助于解释这个概念 我的弹出窗口:entertime.zul <windo

我的应用程序的一部分是记录比赛的完成时间。由于这很可能是在手机或平板电脑上完成的,我想实现一个小弹出窗口,以便轻松修改时间,而无需精确设置焦点并键入时间。但是,将每个完成时间的开始时间设置为00:00:00将使过程非常困难,因此我希望将其初始化为最后输入的完成时间。如果输入的时间在网格的顶部,我希望弹出窗口直接显示在时间框的下方;如果输入的时间在网格的底部,则弹出窗口显示在时间框的上方。下面是我的代码的精简版本,希望有助于解释这个概念

我的弹出窗口:entertime.zul

<window viewModel="@id('vmtp') @init('EnterTimeVM')" onBlur="@command('close')">
    <caption>
        <toolbarbutton label="Save" onClick="@command('save')"/>
        <toolbarbutton label="Cancel" onClick="@command('close')"/>
    </caption>
    <hlayout>
        <vlayout>
            <button label="+" onClick="@command('changeHours', amount='1')" />
            <intbox value="@load(vmtp.hours)" readonly="true" />
            <button label="-" onClick="@command('changeHours', amount='-1')" />
        </vlayout>
        <vlayout>
            <button label="+" onClick="@command('changeMinutes', amount='1')" />
            <intbox value="@load(vmtp.minutes)" readonly="true" />
            <button label="-" onClick="@command('changeMinutes', amount='-1')" />
        </vlayout>
        <vlayout>
            <button label="+" onClick="@command('changeSeconds', amount='1')" />
            <intbox value="@load(vmtp.seconds)" readonly="true" />
            <button label="-" onClick="@command('changeSeconds', amount='-1')" />
        </vlayout>
    </hlayout>
</window>
TimeKeeperVM.java

public class TimeKeeperVM {
    private List<Competitor> competitors;
    private Competitor selectedCompetitor;
    private LocalDateTime prevFinishTime;

    @Init
    public void timeKeeperInit() {
        prevInitTime = LocalDateTime.now();
    }

    public List<Competitor> getCompetitors() {
        return competitors;
    }

    @Command
    public void changeFinishTime(@BindingParam("comp") Competitor competitor,
                @ContextParam(ContextType.COMPONENT) Component timebox) {
        selectedCompetitor = competitor;
        Map<String, Object> args = new HashMap<>();
        LocalDateTime currentFinishTime = competitor.getFinishTime();
        args.put("initTime", (currentFinishTime != null) ? currentFinishTime : prevFinishTime);
        Window win = (Window) Executions.createComponents("entertime.zul", timebox.getParent(), args);
        // Need to use the parent of timebox in this case
        win.setPosition("parent,bottom,right"); // positions the popup relative to timebox parent, not timebox
        win.doPopup();
    }

    @GlobalCommand
    @NotifyChange("competitors")
    public void finishTime(@BindingParam("finishTime") LocalDateTime finishTime) {
        if (selectedCompetitor != null && finishTime != null) {
            selectedCompetitor.setFinishTime(finishTime);
            prevFinishTime = finishTime;
        }
    }
}
然后通过以下方式显示:

onFocus='timepop.open(self,@load(vm.popupPosition))'
问题是我无法将参数传递给
entertime.zul
。我也不能修改弹出窗口的位置,因为
popupPosition
将在渲染时解析;不是运行时。如果包含行(从上方)更改为:

<include initTime="@load(vm.prevFinishTime)" src="entertime.zul" />

initTime
在渲染时初始化;不是运行时


非常感谢您的任何想法/建议。

我更愿意使用Executions.createComponents解决方案

如果所有窗口的模式窗口位置相同,我通常直接标记窗口组件中的位置:

<window viewModel="@id('vmtp') @init('EnterTimeVM')" onBlur="@command('close')" position="parent, bottom, right" width="100px">

而不是将其设置为虚拟机

那么,你有没有试着去掉这个位置?在我的测试项目和您的代码中,将在timebox.getParent()旁边打开弹出窗口

在您的代码中,timebox.getParent是组件行,因此,例如,行宽度可能会有问题

您可以在时间框之前使用父组件(如hbox)绕过此问题

<hbox>
    <timebox format="HH:mm:ss" value="@bind(each.finishTime)" onFocus="@command('changeFinishTime', comp=each)" />
</hbox>

这样父级结果就更有用了


我更喜欢使用Executions.createComponents解决方案

如果所有窗口的模式窗口位置相同,我通常直接标记窗口组件中的位置:

<window viewModel="@id('vmtp') @init('EnterTimeVM')" onBlur="@command('close')" position="parent, bottom, right" width="100px">

而不是将其设置为虚拟机

那么,你有没有试着去掉这个位置?在我的测试项目和您的代码中,将在timebox.getParent()旁边打开弹出窗口

在您的代码中,timebox.getParent是组件行,因此,例如,行宽度可能会有问题

您可以在时间框之前使用父组件(如hbox)绕过此问题

<hbox>
    <timebox format="HH:mm:ss" value="@bind(each.finishTime)" onFocus="@command('changeFinishTime', comp=each)" />
</hbox>

这样父级结果就更有用了


我希望将弹出窗口相对于其所连接的行进行定位。我没有正确阅读的api。它表示
相对于其父窗口定位窗口。也就是说,左上角是相对于其父对象左上角的偏移。
但我可以使用会话属性操纵位置:

@Command
public void changeFinishTime(@BindingParam("comp") Competitor competitor,
    @ContextParam(ContextType.COMPONENT) Component timebox) {
    selectedCompetitor = competitor;
    // set args map
    Window win = (Window) Executions.createComponents("entertime.zul", timebox.getParent(), args);
    Sessions.getCurrent().setAttribute("top", "-20px");
    win.doPopup();
}
然后更改entertime.zul:

<window viewModel="@id('vmtp') @init('EnterTimeVM')" onBlur="@command('close')" position="parent" top="${sessionScope.top}" width="100px">

我希望将弹出窗口相对于其所连接的行进行定位。我没有正确阅读的api。它表示
相对于其父窗口定位窗口。也就是说,左上角是相对于其父对象左上角的偏移。
但我可以使用会话属性操纵位置:

@Command
public void changeFinishTime(@BindingParam("comp") Competitor competitor,
    @ContextParam(ContextType.COMPONENT) Component timebox) {
    selectedCompetitor = competitor;
    // set args map
    Window win = (Window) Executions.createComponents("entertime.zul", timebox.getParent(), args);
    Sessions.getCurrent().setAttribute("top", "-20px");
    win.doPopup();
}
然后更改entertime.zul:

<window viewModel="@id('vmtp') @init('EnterTimeVM')" onBlur="@command('close')" position="parent" top="${sessionScope.top}" width="100px">

这个答案确实为我指明了正确的方向。下面概述了对这个答案的修改。这个答案确实为我指明了正确的方向。对该答案的修改概述如下。
Window win = (Window) Executions.createComponents("entertime.zul", timebox.getParent(), args);
win.setPosition("parent");
win.setTop("-20px");
win.doPopup();