11

我正在编写一个概念验证应用程序,这非常简单。基本上,它由一个 UI 组成,其中在 QML ListView 中显示“Note”类型对象的列表。

然后我有几门课是这样的:

#ifndef NOTE_H
#define NOTE_H

#include <string>

using namespace std;
class Note
{
public:
    Note(QObject* parent = 0)
        : QObject(parent)
    {

    }

    Note(const int id, const string& text)
        : _id(id), _text(text)
    {
    }

    int id()
    {
        return _id;
    }

    const string text()
    {
        return _text;
    }

    void setText(string newText)
    {
        _text = newText;
    }

private:
    int _id;
    string _text;
};

#endif // NOTE_H

然后是一个存储库:

class NoteRepository : public Repository<Note>
{
public:
    NoteRepository();
    ~NoteRepository();

    virtual shared_ptr<Note> getOne(const int id);
    virtual const unique_ptr<vector<Note>> getAll();
    virtual void add(shared_ptr<Note> item);
private:
    map<int, shared_ptr<Note>> _cachedObjects;
};

最后是一个向 QML 公开 Note 的 ViewModel

class MainViewModel : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<Note> notes READ notes NOTIFY notesChanged)
    Q_PROPERTY(int count READ count() NOTIFY countChanged)
public:
    MainViewModel(QObject *newParent = 0);
    int count();
    QQmlListProperty<Note> notes();
signals:
    void notesChanged();
    void countChanged();
public slots:
private:
    std::shared_ptr<UnitOfWork> _unitOfWork;
    static void appendNote(QQmlListProperty<Note> *list, Note *note);
    QList<Note*> _notes;
};

请不要介意这里有任何 C++ 错误,并注意它们是不完整的,这不是此刻的重点,因为我在学习的过程中不断地适应它。

我苦苦挣扎的一点是,如何将类似列表的对象公开给 QML?要求是此列表必须是动态的,应该能够添加、删除和修改注释的文本。当列表被 C++ 修改时,它也应该通知 UI(信号)。

我尝试了 QQmlListProperty,但想不出将它暴露给 QML 的方法。然后我在另一篇 SO 帖子上阅读了这种类型不能被 QML 修改(??),我偶然发现了 QAbstractItemModel。

无论如何,谁能指出我正确的方向?

4

2 回答 2

10

我在另一个答案中发布了一个相当完整的示例。

一般程序是:

  1. 创建一个派生自 的模型QAbstractItemModel。您可以重用 Qt 已经提供的任何模型,例如QStringListModel.

  2. 将其暴露给 QML。例如使用setContextProperty()QML 引擎的rootContext().

  3. 模型的角色在 QML 中的委托上下文中是可见的。Qt在默认实现中为DisplayRole( display) 和EditRole( )提供名称和角色之间的默认映射。editroleNames()

    delegate: Component {
        TextInput {
            width: view.width // assuming that view is the id of the view object
            text: edit // "edit" role of the model, to break the binding loop
            onTextChanged: model.display = text // "display" role of the model
        }
    }
    
  4. 如果需要,您可以通过在视图和后端模型之间附加代理模型来创建中间视图模型。您可以派生自QAbstractProxyModel其子类或其子类之一。

于 2013-09-06T09:29:18.223 回答
1

接受的答案是正确的,除了一个细节。在 MVVM 中,您会将 ViewModel 暴露给 QML,而不是 Model。

于 2021-04-11T11:12:40.197 回答