jface databinding:重写doSetValue方法ComputedValue实现双向多对一的数据绑定

需求说明

如下是一个简单的测试对话框,我们希望当”起始日期”按钮为勾选时,数据对象dataBean的date属性为日期组件DateTime选择的值,否则为null.

先给出DateBean的类定义

    // 具备PropertyChangeSupport支持的JavaBean
    public class DateBean{
        private PropertyChangeSupport support=new PropertyChangeSupport(this);
        public void addPropertyChangeListener(PropertyChangeListener listener) {
            support.addPropertyChangeListener(listener);
        }

        public void removePropertyChangeListener(PropertyChangeListener listener) {
            support.removePropertyChangeListener(listener);
        }

        public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
            support.firePropertyChange(propertyName, oldValue, newValue);
        }

        Date date;

        public Date getDate() {
            return date;
        }

        public void setDate(Date date) {
            System.out.printf("date=%s\n", date);
            firePropertyChange("date", this.date, this.date = date);
        }

ISideEffect

在这个场景中,是两个widget组件的状态绑定到一个数据对象的属性 实现上面的需求,参考我之前的博文《jface databinding:更简单的ISideEffect实现多目标单边数据绑定塈其原理分析》,可以很简单的实现。

    DateTime dateTime=new DateTime(container, SWT.BORDER);
    Button chkDateEnable=new Button(container, SWT.CHECK);
    //。。。。。
    DataBindingContext bindingContext = new DataBindingContext();
    // 创建dateTime日期组件的观察对象
    IObservableValue observeSelectionDateTimeObserveWidget = WidgetProperties.selection().observe(dateTime);
    // 创建chkDateEnable按钮的观察对象
    IObservableValue observeSelectionChkDateEnableObserveWidget = WidgetProperties.selection().observe(chkDateEnable);
    // 创建ISideEffect实现dateTime+chkDateEnable->dateBean.date的单向数据绑定
    ISideEffect.create(()->{
        return (boolean)observeSelectionChkDateEnableObserveWidget.getValue()?(Date)observeSelectionDateTimeObserveWidget.getValue():null;
    }, dateBean::setDate);

ComputedValue

但是,上面的代码只是实现了单向的数据绑定,如果希望在上图中按”恢复缺省值”时,dateBean.date修改后,界面的chkDateEnable和dateTime组件也同步更新,就不能使用ISideEffect了。

我们知道ComputedValue也可以实现单向的多对一数组绑定,

关于ComputedValue,我在另一篇博文中有更详细的介绍《jface databinding:延迟计算–ComputedValue和WritableList使用的例子》

但ComputedValue并没有实现doSetValue方法,所以如果对ComputedValue对象执行setValue方法会抛出UnsupportedOperationException异常,所以ComputedValue是单向的绑定。但是如果我们实现了doSetValue方法,就可以实现双向的数据绑定。

    DateTime dateTime=new DateTime(container, SWT.BORDER);
    Button chkDateEnable=new Button(container, SWT.CHECK);
    //。。。。。
    DataBindingContext bindingContext = new DataBindingContext();
    // 创建dateTime日期组件的观察对象
    IObservableValue observeSelectionDateTimeObserveWidget = WidgetProperties.selection().observe(dateTime);
    // 创建chkDateEnable按钮的观察对象
    IObservableValue observeSelectionChkDateEnableObserveWidget = WidgetProperties.selection().observe(chkDateEnable);
    // 创建ComputedValue对象
    IObservableValue<Date> observableDate = new ComputedValue<Date>(){
        // 重写doSetValue,
        // 当value为null时,chkDateEnable不勾选,dateTime设置为disable
        // value不为null时,chkDateEnable勾选,dateTime设置为enable,并将dateTime组件的日期设置为value的日期
        @Override
        protected void doSetValue(Date value) {
            chkDateEnable.setSelection(null!=value);
            dateTime.setEnabled(null!=value);
            if(null!=value){
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(value);
                dateTime.setDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONDAY), calendar.get(Calendar.DAY_OF_MONTH));
            }                   
        }

        @Override
        protected Date calculate() {
            // 根据chkDateEnable的selection状态,返回Date对象
            // chkDateEnable.selection为true时,返回dateTime的值,设置dateTime为enable
            // chkDateEnable.selection为false时,返回null,设置dateTime为disable
            boolean selection = (boolean)observeSelectionChkDateEnableObserveWidget.getValue();
            dateTime.setEnabled(selection);
            return selection?(Date)observeSelectionDateTimeObserveWidget.getValue():null;
        }

    };
    // 对observableDate对象与dateBean.date属性进行数据绑定
    bindingContext.bindValue(observableDate, dateDateBeanObserveValue, null, null);

完整示例代码

TestComputedValue2 .java

package testwb;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Calendar;
import java.util.Date;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;


import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.sideeffect.ISideEffect;
import org.eclipse.core.databinding.observable.value.ComputedValue;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.swt.DisplayRealm;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

public class TestComputedValue2 extends Dialog {
    private DataBindingContext m_bindingContext;
    public class DateBean{
        private PropertyChangeSupport support=new PropertyChangeSupport(this);
        public void addPropertyChangeListener(PropertyChangeListener listener) {
            support.addPropertyChangeListener(listener);
        }

        public void removePropertyChangeListener(PropertyChangeListener listener) {
            support.removePropertyChangeListener(listener);
        }

        public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
            support.firePropertyChange(propertyName, oldValue, newValue);
        }

        Date date;

        public Date getDate() {
            return date;
        }

        public void setDate(Date date) {
            System.out.printf("date=%s\n", date);
            firePropertyChange("date", this.date, this.date = date);
        }
    }
    private DateBean dateBean=new DateBean();
    private DateTime dateTime;
    private Button chkDateEnable;
    /**
     * Create the dialog.
     * @param parentShell
     */
    public TestComputedValue2(Shell parentShell) {
        super(parentShell);
    }

    /**
     * Create contents of the dialog.
     * @param parent
     */
    @Override
    protected Control createDialogArea(Composite parent) {
        Composite container = (Composite) super.createDialogArea(parent);
        container.setLayout(null);

        dateTime = new DateTime(container, SWT.BORDER);
        dateTime.setBounds(86, 95, 88, 24);

        chkDateEnable = new Button(container, SWT.CHECK);
        chkDateEnable.setBounds(10, 99, 70, 17);
        chkDateEnable.setText("起始日期");

        Button btnNewButton = new Button(container, SWT.NONE);
        btnNewButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                dateBean.setDate(new Date());
            }
        });
        btnNewButton.setBounds(10, 167, 80, 27);
        btnNewButton.setText("恢复缺省值");

        return container;
    }

    /**
     * Create contents of the button bar.
     * @param parent
     */
    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
        createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
        m_bindingContext = initDataBindings();
    }

    /**
     * Return the initial size of the dialog.
     */
    @Override
    protected Point getInitialSize() {
        return new Point(450, 300);
    }
    protected DataBindingContext initDataBindings() {
        DataBindingContext bindingContext = new DataBindingContext();
        //
        IObservableValue observeSelectionDateTimeObserveWidget = WidgetProperties.selection().observe(dateTime);
        IObservableValue observeSelectionChkDateEnableObserveWidget = WidgetProperties.selection().observe(chkDateEnable);
        IObservableValue dateDateBeanObserveValue = BeanProperties.value("date").observe(dateBean);
        //bindingContext.bindValue(observeSelectionDateTimeObserveWidget, dateDateBeanObserveValue, null, null);
        /*IObservableValue<Date> observableDate = ComputedValue.create(()->{
            return chkDateEnable.getSelection()?(Date)observeSelectionDateTimeObserveWidget.getValue():null;
        });*/
        // 创建ComputedValue对象
        IObservableValue<Date> observableDate = new ComputedValue<Date>(){
            // 重写doSetValue,
            // 当value为null时,chkDateEnable不勾选,dateTime设置为disable
            // value不为null时,chkDateEnable勾选,dateTime设置为enable,并将dateTime组件的日期设置为value的日期
            @Override
            protected void doSetValue(Date value) {
                chkDateEnable.setSelection(null!=value);
                dateTime.setEnabled(null!=value);
                if(null!=value){
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(value);
                    dateTime.setDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONDAY), calendar.get(Calendar.DAY_OF_MONTH));
                }                   
            }

            @Override
            protected Date calculate() {
                // 根据chkDateEnable的selection状态,返回Date对象
                // chkDateEnable.selection为true时,返回dateTime的值,设置dateTime为enable
                // chkDateEnable.selection为false时,返回null,设置dateTime为disable
                boolean selection = (boolean)observeSelectionChkDateEnableObserveWidget.getValue();
                dateTime.setEnabled(selection);
                return selection?(Date)observeSelectionDateTimeObserveWidget.getValue():null;
            }

        };
        // 对observableDate对象与dateBean.date属性进行数据绑定
        bindingContext.bindValue(observableDate, dateDateBeanObserveValue, null, null);
        /*ISideEffect.create(()->{
            return (boolean)observeSelectionChkDateEnableObserveWidget.getValue()?(Date)observeSelectionDateTimeObserveWidget.getValue():null;
        }, dateBean::setDate);*/
        //
        return bindingContext;
    }
    public static void main(String[] args) {
        Display display = Display.getDefault();
        Realm.runWithDefault(DisplayRealm.getRealm(display), new Runnable() {
            public void run() {
                try {
                    TestComputedValue2 setting = new TestComputedValue2(null);
                    setting.open();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我和未来有约会

Silverlight第三方控件专题

这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏请告知我一下。 名称 简介 截图 telerik 商 RadC...

4355
来自专栏我和未来有约会

Kit 3D 更新

Kit3D is a 3D graphics engine written for Microsoft Silverlight. Kit3D was inita...

2886
来自专栏魂祭心

原 canvas绘制clock

5004
来自专栏跟着阿笨一起玩NET

c#实现打印功能

3592
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

5208
来自专栏张善友的专栏

Mix 10 上的asp.net mvc 2的相关Session

Beyond File | New Company: From Cheesy Sample to Social Platform Scott Hansel...

2767
来自专栏c#开发者

为什么nhibernate 不能保存on-to-many的结构

下面是主类文件 Code namespace EasyTalk.Module {     /// <summary>     /// SiteAddre...

2565
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.4K7
来自专栏张善友的专栏

LINQ via C# 系列文章

LINQ via C# Recently I am giving a series of talk on LINQ. the name “LINQ via C...

2965
来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

8368

扫码关注云+社区