QML:更新嵌套的 ListView

QML: Update a nested ListView

我正在制作一个关于 Sailfish 的电视指南 OS,并且遇到了一个 - 目前 - 障碍。 因为我想有可能为自定义列表标记每个条目 我需要修改后面的模型。我试过直接修改模型: model.favorite = true 但这不起作用。我试图修改底层 arrayOfObjects,但这并未反映在 UI 中,而且我无法触发更新,因为我无法访问 ListView。我试过做一个定制的模型,但是因为我不能引用它的实例,所以没有用。

下面是一个非常简化的布局表示,主要使用基本的 QML。

Page {
    Flickable {
        Column {
            SlideshowView { // PathView
                model: arrayOfObjects
                delegate: channelDelegate
            }
        }
    }

    Component {
        id: channelDelegate
        ListView {
            id: channelList
            // ProgramModel just iterates thru arrayOfObjects and appends them
            model: ProgramModel {
                programs: arrayOfObjects
            }
            delegate: programDelegate
            Component.onCompleted: {
                // I can't reference channelList from here.
            }
        }
    }

    Component {
        id: programDelegate
        ListItem {
            Button {
                onClicked: {
                    // How do I reference channelList?
                    // Doing it by name doesn't work.
                }
            }
        }
    }
}

我试过调用 ApplicationWindow(有效)来发送一个我连接到的信号 在 channelList.onCompleted 中(也有效),但由于我无法从中引用列表 那里没有帮助。

我使用的是 QT 5.6,所以某些解决方案可能不起作用。 而且我真的更愿意保持它是纯 QML;没有 C++。

我无法准确重现你的案例,但也许这个简单的例子能以某种方式帮助你。

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.2

Window {
    id: mainWrapper
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    signal updateModel(int id, string name)

    Component {
        id: listWrapper

        ListView {
            id: list

            model: [
               { name: "name0" },
               { name: "name1" },
               { name: "name2" }
           ]

            delegate: Loader {
                width: parent.width
                property variant model: modelData
                property int modelIndex: index
                sourceComponent: listDelegate
            }

            function updateModelName(id, name) {
                var listModel = list.model
                listModel[id].name = name
                list.model = listModel
            }
        }
    }

    Loader {
        id: loadedList
        x: 0
        anchors.fill: parent
        sourceComponent: listWrapper

        Component.onCompleted: {
            mainWrapper.updateModel.connect(loadedList.item.updateModelName)
        }
    }

    Component {
        id: listDelegate

        Rectangle {
            id: listRow
            width: 200
            height: 80
            Text {
                text: model.name
            }

            Button {
                x: 100
                text: "update"
                onClicked: {
                    mainWrapper.updateModel(modelIndex, "better_name"+modelIndex)
                }
            }
        }
    }
}

这个例子的线索是使用信号和函数来更新模型。

由于SlideshowView 取代了DaszuOne 的答案中的焦点,即切换幻灯片,list.model = listModel 导致整个视图发生变化。更改模型中的单个条目不会触发更新,因此需要更多代码才能实现。因此,在反复考虑之后,我决定这样做 "the right way" 会比简单的方法更麻烦和难以阅读。

我做了一个很简单的wrapper,你用什么样的持久化存储就可以用,只有两个方法:setFavorite()isFavorite

在委托中,我更新了 onCompleted 中的 属性,因此每次需要渲染元素时都会调用它:

    Component.onCompleted: {
        favorite = favorites.isFavorite(model.channelId, model.id)
    }

我的结论是,DaszuOne 的答案是正确的 - 但在这种情况下不是;)

感谢大家的帮助,让我更好地理解了QML。