【问题标题】:Databind and validate a TableViewer?数据绑定和验证 TableViewer?
【发布时间】:2011-03-22 19:15:59
【问题描述】:

我使用org.eclipse.core.databinding 框架在SWT 应用程序中绑定一些Text 字段。我添加了一个更新策略来验证数据并仅在用户单击保存按钮时才在模型上设置值:

    UpdateValueStrategy toModel = new UpdateValueStrategy(UpdateValueStrategy.POLICY_CONVERT);
    if (validator != null) {
        toModel.setAfterGetValidator(validator);
    }

    UpdateValueStrategy fromModel = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE);

    binding = bindingContext.bindValue(SWTObservables.observeText(this, SWT.Modify),
                    BeansObservables.observeValue(pVO, propertyName), toModel, fromModel);

这段代码真的很好用。

但是我怎样才能在TableViewer 上做同样的事情呢?

我希望它能够工作,以便当我在 IHM 中添加某些内容时,模型保持不变,直到我调用 getBindingContext().updateModels();

【问题讨论】:

    标签: java data-binding jface


    【解决方案1】:

    您不需要使用TableViewer 中的JFace 数据绑定框架。处理结构化数据比 SWT 控件更简单,例如TableViewerListViewerTreeViewer。您可以以相同的方式使用这些查看器:

    • 创建查看器
    • 设置内容提供者
    • 设置标签提供者(建议)
    • 设置过滤器(可选)
    • 设置排序器(可选)

    查看器创建后,只需调用viewer.setInput(data) 即可将所有内容放到查看器中。

    有一个型号列表:

    TableViewer tableViewer = new TableViewer(parent); 
    
    Table table = tableViewer.getTable(); 
    table.setHeaderVisible(true);      
    table.setLinesVisible(true);`
    
    for (int i = 0; i < COLUMN_NAMES.length; i++) {
        TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
        tableColumn.setText(COLUMN_NAMES[i]);
        tableColumn.setWidth(COLUMN_WIDTHS[i]);
    }
    
    tableViewer.setContentProvider(new ModelContentProvider());
    tableViewer.setLabelProvider(new ModelLabelProvider());
    tableViewer.setInput(models);
    

    奇迹发生在内容提供者身上:

    class ModelContentProvider implements IStructuredContentProvider {
    
        @SuppressWarnings("unchecked")
        @Override
        public Object[] getElements(Object inputElement) {
            // The inputElement comes from view.setInput()
            if (inputElement instanceof List) {
                List models = (List) inputElement;
                return models.toArray();
            }
            return new Object[0];
        }
    
    /* ... other methods */
    
    }
    

    每个模型都将成为TableItemTableItem(item.getData()) 中的模型。

    但是,一个由许多列组成的表,你需要LabelProvider来帮助你将模型的属性映射到TableItem

    class ModelLabelProvider extends LabelProvider implements
            ITableLabelProvider {
    
        @Override
        public Image getColumnImage(Object element, int columnIndex) {
            // no image to show
            return null;
        }
    
        @Override
        public String getColumnText(Object element, int columnIndex) {
            // each element comes from the ContentProvider.getElements(Object)
            if (!(element instanceof Model)) {
                return "";
            }
            Model model = (Model) element;
            switch (columnIndex) {
            case 0:
                return model.getFoo();
            case 1:
                return model.getBar();
            default:
                break;
            }
            return "";
        }
    }
    

    将模型传播到查看器很容易。如果您将查看器传播到绑定模型,使用CellEditor 也很简单。 要使用CellEditor,您需要将列属性、单元格编辑器和单元格修饰符设置为TableViewer

    tableViewer.setColumnProperties(COLUMNS_PROPERTIES);
    tableViewer.setCellEditors(new CellEditor[] {
            new TextCellEditor(table), new TextCellEditor(table) });
    tableViewer.setCellModifier(new ModelCellModifier(tableViewer));
    

    CellModifier 喜欢这样:

    class ModelCellModifier implements ICellModifier {
        TableViewer viewer;
    
        public ModelCellModifier(TableViewer viewer) {
            this.viewer = viewer;
        }
    
        @Override
        public boolean canModify(Object element, String property) {
            // property is defined by viewer.setColumnProperties()
            // allow the FOO column can be modified.
            return "foo_prop".equals(property);
        }
    
        @Override
        public Object getValue(Object element, String property) {
            if ("foo_prop".equals(property)) {
                return ((Model) element).getFoo();
            }
            if ("bar_prop".equals(property)) {
                return ((Model) element).getBar();
            }
            return "";
        }
    
        @Override
        public void modify(Object element, String property, Object value) {
            if ("foo_prop".equals(property)) {
                TableItem item = (TableItem) element;
                ((Model) item.getData()).setFoo("" + value);
    
                // refresh the viewer to show the changes to our user.
                viewer.refresh();
            }
        }
    }
    

    一切都很简单,但有很多步骤可以一起完成。

    【讨论】:

    • ...但是您为什么要放弃数据绑定并返回编写大量样板代码?
    • 小注释:tableViewer.setColumnProperties(COLUMNS_PROPERTIES); 表示在COLUMN_PROPERTIES 中您必须提供所有列名 - 或者只使用COLUMN_NAMES
    【解决方案2】:

    我同意qualidafial。

    来自jface.databinding sn-ps 的Snippet017TableViewerWithDerivedColumns 就是一个完整的例子。

    【讨论】:

    【解决方案3】:

    使用 ViewerSupport:

    TableViewer tableViewer = ...
    IObservableList tableElements = ...
    IValueProperty[] columnProperties = ...
    ViewerSupport.bind(tableViewer, tableElements, columnProperties);
    

    【讨论】:

    • 这似乎是一个很好的解决方案。但是有什么方法可以将验证器和转换器与表格查看器一起使用吗?
    猜你喜欢
    • 2013-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-08
    • 2017-07-25
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多