如何在 Qt/C++/QML 中实现类似 WPF 的 MVVM? [英] How to implement WPF-like MVVM in Qt/C++/QML?
问题描述
我正在编写一个概念验证应用程序,这非常简单.基本上它由一个 UI 组成,其中Note"类型对象的列表显示在 QML ListView 中.
I'm writing a proof of concept application, that is very simple. Basically it's composed of a UI where a list of "Note" type objects is displayed in a QML ListView.
然后我有一些类,大致上是这样的:
I then have a few classes which is something along the lines:
#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
Finally a ViewModel that exposes Note to QML
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(信号).
The point where I'm struggling is, how to expose a list-like object to QML? The requirement is this list must be dynamic, one should be able to add, delete and modify the text of a note. When the list is modified by C++, it should also notify the UI (signal).
我尝试了 QQmlListProperty,但找不到将其暴露给 QML 的方法.然后我在另一篇 SO 文章中阅读了 QML 无法修改这种类型 (??),然后我偶然发现了 QAbstractItemModel.
I tried QQmlListProperty, but couldn't figure a way of exposing it to QML. Then I read on another SO post this type can't be modified by QML (??), and I stumbled upon QAbstractItemModel.
无论如何,有人能指出我正确的方向吗?
Anyhow, can anyone point me to the right direction?
推荐答案
我在 另一个答案.
一般程序是:
创建一个从
QAbstractItemModel
派生的模型.您可以重用 Qt 已经提供的任何模型,例如QStringListModel
.
Create a model that derives from
QAbstractItemModel
. You can reuse any of the models already provided by Qt, for exampleQStringListModel
.
将其暴露给 QML.例如.使用 QML 引擎的 rootContext()
的 setContextProperty()
.
Expose it to QML. E.g. use setContextProperty()
of QML Engine's rootContext()
.
模型的角色在 QML 的委托上下文中可见.Qt 在默认情况下为 DisplayRole
(display
) 和 EditRole
(edit
) 提供了名称和角色之间的默认映射roleNames()
的实现.
The model's roles are visible in the context of the delegate in QML. Qt provides default mapping between names and roles for the DisplayRole
(display
) and EditRole
(edit
) in a default implementation of roleNames()
.
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
}
}
如果需要,您可以通过在视图和后端模型之间附加代理模型来创建中间视图模型.您可以从 QAbstractProxyModel
或其子类之一派生.
这篇关于如何在 Qt/C++/QML 中实现类似 WPF 的 MVVM?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!