已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也

XXXXXXXXXXXXXXXXXXXXXXXXX/questions/18648257/how-to-implement-wpf-like-mvvm-in-qt-c-qml

How to implement WPF-like MVVM in Qt/C++/QML?

Ask Question

Asked 6 years, 2 months ago

Active 2 years, 7 months ago

Viewed 13k times

11

4

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</string>

Then a repository:

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;
};</int, shared_ptr<note></note></vector<note></note></note>

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;
};</note*></note></unitofwork></note></note>

PLEASE DON'T MIND ANY C++ MISTAKES HERE and mind they are incomplete, it's not the point at this moment as I'm constantly adapting this as I learn.

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).

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?

   




johnildergleidisson

1,85933 gold badges2727 silver badges4545 bronze badges

add a comment

1 Answer

activeoldestvotes

9

I've posted a rather complete example in another answer.

The general procedure is:

  1. Create a model that derives from QAbstractItemModel. You can reuse any of the models already provided by Qt, for example QStringListModel.

  2. Expose it to QML. E.g. use setContextProperty() of QML Engine's rootContext().

  3. 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
        }
    }
  4. You can create intermediate viewmodels, if needed, by attaching proxy models between the views and the backend models. You can derive from QAbstractProxyModel or one of its subclasses.


文号 / 866851

千古风流
名片专栏发私信
学术分 1
总主题 145 帖总回复 1861 楼拥有证书:进士 学者 机友 笔友
注册于 2010-12-30 03:32最后登录 2024-04-23 15:18
主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:未同步

个人简介

暂未填写
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

插入资源
全部
图片
视频
音频
附件
全部
未使用
已使用
正在上传
空空如也~
上传中..{{f.progress}}%
处理中..
上传失败,点击重试
等待中...
{{f.name}}
空空如也~
(视频){{r.oname}}
{{selectedResourcesId.indexOf(r.rid) + 1}}
处理中..
处理失败
插入表情
我的表情
共享表情
Emoji
上传
注意事项
最大尺寸100px,超过会被压缩。为保证效果,建议上传前自行处理。
建议上传自己DIY的表情,严禁上传侵权内容。
点击重试等待上传{{s.progress}}%处理中...已上传,正在处理中
空空如也~
处理中...
处理失败
加载中...
草稿箱
加载中...
此处只插入正文,如果要使用草稿中的其余内容,请点击继续创作。
{{fromNow(d.toc)}}
{{getDraftInfo(d)}}
标题:{{d.t}}
内容:{{d.c}}
继续创作
删除插入插入
插入公式
评论控制
加载中...
文号:{{pid}}
加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}
ID: {{user.uid}}