2

MVVM パターンでツリーを作成したいと思います。

そして、このツリーには、パラメーターによって渡される 2 つのディレクトリが必要です。目標は、ディレクトリ エクスプローラーを作成することです。パフォーマンスを向上させるために、子が開かれたときに「オンデマンドでロード」したいと考えています。

とりあえず、ドキュメントに例がありますが、不完全です:

public class TreeSelectionVM {

    private TreeModel<TreeNode<String>> itemTree;
    private String pickedItem;
    //omit getter and setter for brevity
}

<window apply="org.zkoss.bind.BindComposer"
    viewModel="@id('vm') @init('org.zkoss.reference.developer.mvvm.collection.TreeSelectionVM')">
    <tree id="tree" model="@bind(vm.itemTree) " width="600px"
    selectedItem="@bind(vm.pickedItem)">
        <treecols>
            <treecol label="name" />
            <treecol label="index" />
        </treecols>
        <template name="model" var="node" status="s">
            <treeitem open="@bind(node.open)">
                <treerow>
                    <treecell label="@bind(node.data)" />
                    <treecell label="@bind(s.index)" />
                </treerow>
            </treeitem>
        </template>
    </tree>
</window>

onOpen イベントを管理する必要がありますか? それとも、TreeModel および TreeNode メソッド (getChild & co) を実装する必要がありますか?

ありがとうございました。

4

3 に答える 3

3

これは、オンデマンドでロードを実行するディレクトリエクスプローラーのラインに沿った、より完全なzkmvvmツリーの例です。

https://github.com/simbo1905/zktreemvvm

「gitclone」でチェックアウトしてから、次のコマンドで実行してください。

mvn -Djetty.port=8080 package jetty:run

コードは、指定されたポートで独自のJettyサーバーを起動します。

これは、モックや単体テストが難しい生のjava.io.Fileを使用するのではなく、ファイルシステムの抽象化としてApacheCommonsVFSを使用します。デフォルトでは、コードは、通常のファイルやフォルダーであるかのようにcommons-vfs2-2.0.jarの内部を参照するためのZK画面を表示します。ViewModelクラスのFILE_SYSTEM_URIuriを「file:/// some / path /」のようなファイルの場所に変更するだけで、通常のファイルシステムを表示できます。

zulページにはツリーが含まれており、そのモデルをvm.treeModelにバインドし、selectedItemイベントをvm.pickedItemメソッドにバインドします。

<?xml version="1.0" encoding="UTF-8"?>
<zk>
    <window apply="org.zkoss.bind.BindComposer"
        viewModel="@id('vm') @init('org.github.simbo1905.zktreemvvm.CommonsVfs220ViewModel')">
        <tree model="@load(vm.treeModel)" selectedItem="@bind(vm.pickedItem)">
            <treecols>
                <treecol label="name" />
                <treecol label="index" />
            </treecols>
            <template name="model" var="node" status="s">
                <treeitem>
                    <treerow>
                        <treecell label="@bind(node) @converter('org.github.simbo1905.zktreemvvm.NodeConverter')" />
                        <treecell label="@bind(s.index)" />
                    </treerow>
                </treeitem>
            </template>
        </tree>
    </window>
</zk>

@Converterは、ツリーモデルに保持されているFileObjectデータのわかりやすいレンダリングを行います。

実際のViewModelはあまり機能しませんが、selectedItemイベントハンドラー(ログのみを実行します)を保持し、TreeModelへのアクセスを提供します。

public TreeModel<FileObject> getTreeModel() {
    if (treeModel == null) {
        try {
            FileSystemManager fsManager = VFS.getManager();
            FileObject fo = fsManager.resolveFile( FILE_SYSTEM_URI );
            treeModel = new CachingVfsTreeModel(fo);
        } catch (FileSystemException e) {
            throw new IllegalArgumentException(String.format("Could not open VFS uri: %s",FILE_SYSTEM_URI),e);
        }
        }
    return treeModel;
}

主な作業は、AbstractTreeModelを拡張し、必須メソッドを定義するVfsTreeModelクラスです。

public class VfsTreeModel extends AbstractTreeModel<FileObject> {

// __ snip __

@Override
public FileObject getChild(FileObject parent, int index) {
    log.info(String.format("%s getChild on %s with index %s", level(parent), innerName(parent), index));
    FileObject child = null;
    try {
        FileObject[] children = parent.getChildren();
        child = children[index];
    } catch (FileSystemException e) {
        throw new IllegalArgumentException(e);
    }
    return child;
}

@Override
public int getChildCount(FileObject node) {
    int childCount = 0;
    try {
        FileType type = node.getType();
        if( type == FileType.FOLDER ){
            childCount = node.getChildren().length;
        }
    } catch (FileSystemException e) {
        throw new IllegalArgumentException(e);
    }
    log.info(String.format("%s getChildCount on %s returning %s",level(node),innerName(node), childCount));
    return childCount;
}

@Override
public boolean isLeaf(FileObject node) {
    boolean isLeaf = false;
    try {
        FileType type = node.getType();
        isLeaf = (type == FileType.FILE );
    } catch (FileSystemException e) {
        throw new IllegalArgumentException(e);
    }
    log.info(String.format("%s isLeaf on %s returning %s", level(node),innerName(node), isLeaf));
    return isLeaf;
}

このバグトラッカーには、フレームワークがその情報を把握するために他の多くの呼び出しを行わないようにgetPathをオーバーライドすることが推奨されていました。

http://tracker.zkoss.org/browse/ZK-1278

そのメソッドは、ルートへのウォークとして実装されます。

@Override
public int[] getPath(FileObject node) {
    List<Integer> paths = new ArrayList<Integer>();
    try {
        FileObject parent = node.getParent();
        while (parent != null && parent.getType().equals(FileType.FOLDER)) {
            FileObject[] children = parent.getChildren();
            for( int index = 0; index < children.length; index++){
                FileObject c = children[index];
                if( node.equals(c)){
                    paths.add(index);
                    break;
                }
            }
            node = parent;
            parent = node.getParent();
        }
    } catch (FileSystemException e) {
        throw new IllegalArgumentException(e);
    }
    int[] p = new int[paths.size()];
    for( int index = 0; index < paths.size(); index++){
        p[index] = paths.get(p.length - 1 - index); // reverse
    }
    log.info(String.format("%s getPath on %s",level(node),innerName(node)));
    return p;
}

次のツリーモデルのドキュメントと「巨大なデータ」のドキュメントでは、キャッシュを推奨しています。

http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/MVC/Model/Tree_Model

http://books.zkoss.org/wiki/ZK%20Developer%27s%20Reference/Performance%20Tips/Listbox,%20Grid%20and%20Tree%20for%20Huge%20Data/Implement%20ListModel%20and%20TreeModel

したがって、サンプルコードでは、ViewModelはVfsViewModelのキャッシングサブクラスを作成します。ページを更新すると、新しいオブジェクトが作成され、キャッシュがガベージコレクションされます。これは、この例ではおそらく十分です。

于 2012-12-26T17:39:52.967 に答える
1

RODTreeModelとRODTreeNodeを実装して、モデル/ノード側とデータ側を分離し、データBeanがRODTreeNodeDataインターフェイスを実装している場合に任意のデータBeanをオンデマンドでロードできるようにしました(2つのメソッドgetChildrenとgetChildCountが含まれています)

基本的な概念/ルールは、データBeanに作業を行わせ、node.getChildren()。size()をnode.getChildCount()に置き換え、必要に応じてdataBean.getChildCountを呼び出すことです。getChildren()をできるだけ遅く延期します。

関連ファイル:

ツリーRODクラスとサンプルファイル

tree_rod_load_on_demand.zul

于 2013-01-02T17:28:57.103 に答える
1

ドキュメントには、独自のものを実装するように指示されてTreeModelおり、私もそうしています;)。詳細については、こちら
を お読みください。

編集

これは一般的な例ですTreeModel
これは単なる一般的な例であり、実装する必要があることを覚えておいてください。キャッシュ
と部分的なロードを自分で行います。

最初のコメントへの返信:

ZK の Data-Models for MeshElements は MVVM や MVC とは独立しており、
cosはfor をmodel="xxx"呼び出すだけで、 ZK が Java で見つけることができる何かに評価される限り、 ZK は式を気にしません。そして、テンプレートはレンダラーを置き換えますsetModel()Component
xxx

例:

.zul ファイル

<window title="new page title" border="normal" apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('web.zk.controller.ListboxMVVM')">
        <listbox model="@load(vm.list)">
            <listhead>
                <listheader />
            </listhead>
            <template name="model">
                <listitem>
                    <listcell label="@load(each.name)" />
                </listitem>
            </template>
        </listbox>
    </window>
</zk>

リストボックスMVVM

public class ListboxMVVM {

    public UsersListModel getList() {
        return new UsersListModel(10, 0);
    }
}

UsersListModel は impl です。のAbstractListModel

MychaL の 2 番目のコメントに返信する

前に述べたように、ZK ドキュメントのこの部分では、実装方法について説明しています。木のモデル。
要するに、

public Object getElementAt(int index);

期待されるコンテンツを取得するために呼び出されます。ロジックの責任、
ロードまたはアンロード、および必要なものをバッファリングする方法はあなた次第です。 返されるオブジェクトは、期待どおり、戻り値の型として読み取るときに
好きなものにすることができます。 データからツリー ノードを生成するには、impl. MVC の方法 ですが、MVVM でも正常に動作するレンダラー、または上記のようにテンプレートを記述 します。
Object

each
getElementAt(int index)

于 2012-12-03T14:34:41.247 に答える