数据绑定后更新不更新 UI 中的内容

Updating after data binding does not update content in UI

抱歉,我现在一定是脑子出了问题,因为我看不出问题出在哪里,应该是微不足道的。我准备了一个简单的场景,我使用 BeanFieldGroup 将字段绑定到 bean 属性,当我单击“更改”和“重置”按钮时,模型设置了正确的值,但 UI 没有被更新。 我正在使用 Vaadin4Spring,但应该不是问题所在。

import com.vaadin.data.fieldgroup.BeanFieldGroup;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.spring.annotation.SpringView;
import com.vaadin.ui.Button;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

import java.io.Serializable;

@SpringView(name = "test")
public class TestView extends VerticalLayout implements View {

    private TextField txtTest = new TextField("Test");
    private Button btnChange = new Button("Click!");
    private Button btnReset = new Button("Reset");

    private TestBean testBean = new TestBean();

    public TestView() {
        txtTest.setImmediate(true);

        addComponent(txtTest);
        addComponent(btnChange);
        addComponent(btnReset);

        BeanFieldGroup<TestBean> binder = new BeanFieldGroup<>(TestBean.class);
        binder.setItemDataSource(testBean);
        binder.setBuffered(false);
        binder.bind(txtTest, "text");

        initComponents();
    }

    private void initComponents() {
        btnChange.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                testBean.setText("Hello world!");
            }
        });

        btnReset.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                testBean.setText("");
            }
        });
    }

    @Override
    public void enter(ViewChangeListener.ViewChangeEvent event) {
        Notification.show("Test");
    }

    public class TestBean implements Serializable {

        private String text;

        public TestBean() {
            text = "";
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

    }

}

您正在直接调用 bean setter,因为 Java 没有提供任何方式来监听那种变化,所以 Vaadin 属性(或 TextField)没有不知道该值已更改。如果您通过 Vaadin 属性 通过说

更改值
binder.getItemDataSource().getItemProperty("text").setValue("new value");

然后您会在 TextField 上看到 "new value",并且由于禁用了缓冲,因此 testBean.getText() 也会 returns "new value"。

我发现的最接近的是 binder.discard(),它强制所有绑定字段从 bean 重新读取它的值。是的,它仍然需要手动调用,但仍然远没有 getItemDataSource().getItemProperty(...).setValue(...) 痛苦。如果对这种蛮力方法有任何顾虑,那么当然可以直接在应该受到影响的字段上调用 ​​Field.discard()