2017-05-04 29 views
0

JavaFXを使用してアプリケーションを作成したいと思います。分割ビュー(afterburner.fxで分割)とmvvmプリンシパルに問題があります。 私のシナリオでは、私は、テキストフィールドとボタンとリストビューを持つ2番目のビューで1つのビューを持っています。 これで、テキストフィールドにテキストを書き込んで、ボタンをクリックしてテキストをリストに追加しました。 私は4つのクラス(テキストフィールド/ボタンとリスト用のビューとビューモデル)を持っています。 質問:ボタンクリックに反応して、テキストフィールドからテキストをリストに転送するにはどうすればよいですか?ViewModelから別のViewModelに値を転送する(JavaFX、mvvm、afterburner.fx)

ビューのテキストとviewModelのプロパティをバインドできます。しかし、値をリストのビューモデルにどのように転送できますか?

誰かがこの理解の問題で私を助けてくれることを願っています。

Big Thanks!

答えて

0

ここでの基本的な考え方は、共有データにアクセスする必要があるコンポーネント間で共有される単一のデータモデルを使用することです。 afterburner.fxで@Injectを使用すると、これを管理する便利な方法が提供されます。

デザインパターンでは、まずafterburner.fx(というよりも多分FXML- "コントローラ"メカニズム)がMVPパターン(MVVMパターンではない)に基づいていることに注意してください。 。 FXMLファイルは(パッシブ)ビューを表します。発表者はもちろん発表者であり、モデルはアプリケーション要件に従って実装されます。

通常、使用しているフレームワークは、どのパターンを使用するかの決定の大きな部分を占めているので、ここではMVPパターンを使用することをお勧めします。 MVPを使用して、これは次のようになります。

あなたはあなたのモデルにObservableListを作成することができます。

public class Model { 

    private final ObservableList<String> itemList = FXCollections.observableArrayList(); 

    public ObservableList<String> getItemList() { 
     return itemList ; 
    } 

} 

次にプレゼンターにListViewを持つビューのために、実行します。

public class ListPresenter { 

    @Inject 
    private Model model ; 

    @FXML 
    private ListView<String> listView ; 

    @FXML 
    public void initialize() { 
     listView.setItems(model.getItemList()); 
    } 
} 

ListViewはモデルのObservableListをそのバッキングリストのアイテムとして使用します。つまり、そのリストが変更されると、ListViewは自動的に更新されます。テキストフィールドを持つビューのためのプレゼンターで

は、あなたが実行します。ボタンが押されたとき

public class AddItemPresenter { 

    @Inject 
    private Model model ; 

    @FXML 
    private TextField textField ; 

    // handler for button press: 
    @FXML 
    private void handleButton() { 
     model.getItemList().add(textField.getText()); 
    } 
} 

は今、テキストフィールド内のテキストは、モデルのアイテムリストに追加されます。そのリストをリストビューのバッキングリストとして設定するため、テキストがリストビューに表示されます。


ここMVVMパターンを強制する場合、私はあなたがアフターバーナーからFXML-プレゼンターペアを含むものとしてMVVMで「ビュー」を考慮しなければならないと思います。つまり、M(VP)VMパターンのようなものになります。私はMVCとMVPのMVVMに精通していませんが、分かりやすいように、使い慣れたデータモデル(M)、ビュー(V)、ビューモデル(VM)の3つのコンポーネントがあります。ビューモデルの役割は、アクションを含むビューの状態を表現することですが、実際のビュー自体については何も知りません。上記の例では、2つのビューモデルがあります。各ビューの1つ。データモデル(M)はまだ存在し、もちろんビューモデルにアクセスする必要があることに注意してください。同じデータモデルインスタンスを共有する必要があるため、同じデータにアクセスして操作することができます。

私はModelクラスは前と同じである

public class ListViewModel { 

    @Inject 
    private Model model ; 

    private final StringProperty selectedItem = new SimpleStringProperty(); 

    public ObservableList<String> getItems() { 
     return model.getItemList(); 
    } 

    public StringProperty selectedItemProperty() { 
     return selectedItem ; 
    } 

    public String getSelectedItem() { 
     return selectedItemProperty().get(); 
    } 

    public void setSelectedItem(String item) { 
     selectedItemProperty().set(item); 
    } 
} 

のように、このの実装が見えると思います。プレゼンター(MVVMでのビュー)の仕事は、ビューモデルにビューをバインドすることです:

public class ListViewPresenter { 

    @Inject 
    private ListViewModel viewModel ; 

    @FXML 
    private ListView<String> listView ; 

    @FXML 
    public void initialize() { 
     listView.setItems(viewModel.getItems()); 
     viewModel.selectedItemProperty().bind(listView.getSelectionModel().selectedItemProperty()); 
    } 
} 

同様に、「アイテムを追加」モジュールのビューモデルが

public class AddItemViewModel { 

    @Inject 
    private Model model ; 

    private final StringProperty currentItem = new SimpleStringProperty(); 

    private final Runnable addItemAction = this::addItem ; 

    public StringProperty currentItemProperty() { 
     return currentItem ; 
    } 

    public String getCurrentItem() { 
     return currentItemProperty().get(); 
    } 

    public void setCurrentItem(String item) { 
     currentItemProperty().set(item); 
    } 

    public Runnable getAddItemAction() { 
     return addItemAction ; 
    } 

    private void addItem() { 
     model.getItemList().add(getCurrentItem()); 
     setCurrentItem(""); 
    } 
} 

AddItemPresenterのように見えます今のように見える

public class AddItemPresenter { 

    @Inject 
    private AddItemViewModel viewModel ; 

    @FXML 
    private TextField textField ; 

    @FXML 
    private Button addButton ; 

    @FXML 
    public void initialize() { 
     viewModel.currentItemProperty().bindBidirectional(textField.textProperty()); 
     addButton.setOnAction(e -> viewModel.getAddItemAction().run()); 
    } 
} 

実際には、ビューと(データ)モデルの間に追加のレイヤーを挿入するだけです。プレゼンターが今や実際には「体重を引っ張っていない」ようなネットエフェクトが感じられます。これは通常、アプリケーションが過剰に設計されていてレイヤーが多すぎることを示しています。しかし、ビューモデルはプレゼンターよりもはるかに「テストに優しい」という利点があります(もちろん、注入されたモデルのセッターまたはコンストラクターパラメーターを提供することでより多くのことを行うことができます)。

+0

答えてくれてありがとうございますが、私は発表者をModel-View-ViewModel原則のビューとして解釈します。だから、ビューロジックはありません。 ListViewのようなビュー要素のみをViewModelで接続します。 この例では、プレゼンターはロジックを持っています listView.setItems(model.getItemList()); model.getItemList()。add(textField.getText()); (これは@Injectと@FXMLのため)実際にテストには向いていません。 私の意見では、ビューモデルはそのコミュニケーションを処理する必要があります。 それは間違った審議ですか? THX – user2558928

+0

@ user2558928 afterburner.fxで使用される基本パターンは、MVP(パッシブビュー)パターンです(これはFXMLクラスと "コントローラ"クラスを使用する場合にも非常に当てはまります)。この上にMVVMデザインを強制するのは難しいでしょう - あなたは何らかのM(VP)VMデザインで終わるでしょう。おそらく、あなたはあなたの質問にいくつかのコードを追加して、あなたの出発点を示すことができますか? –

+0

@ user2558928 MVVMアプローチによるアップデートを参照してください(私はそう思います...)。 –

関連する問題