如何在XmlListModel准备好后才更新QML ListView?

时间:2013-06-17 17:37:42

标签: xml qml qtquick2

我有一个XmlListModel,它最初查询本地XML文件,该文件包含常见世界城市列表及其纬度和经度。如果用户在该本地列表中找不到该城市,则XML ListModel然后查询在线API以检索该城市的纬度和经度。

因此,如代码所示,默认情况下,它使用localCityUrl()函数作为源来显示本地城市列表。

XmlListModel {
        id: searchCityModel;

        source: localCityUrl()
        query: "/geonames/geoname"

        XmlRole { name: "city"; query: "toponymName/string()"; isKey: true }
        XmlRole { name: "country"; query: "countryName/string()"; isKey: true }
        XmlRole { name: "lat"; query: "lat/string()"; isKey: true }
        XmlRole { name: "lng"; query: "lng/string()"; isKey: true }

        onSourceChanged: reload();
    }

ListView {
        id: worldList

        anchors { left: parent.left; right: parent.right }
        height: units.gu(50)
        model: searchCityModel
        currentIndex: -1            

        delegate: Column {
            text: searchCityModel.status == XmlListModel.Ready ? searchCityModel.get(index).city + ", " + searchCityModel.get(index).country : console.log("Loading..")
            selected: worldList.currentIndex == index;
        }
    }

此时一切都很好。但是,当用户在线搜索城市时(因为它在本地列表中不可用),它会更改源以查询在线API,默认情况下总是返回5个结果(与用户搜索词的最佳匹配)。

我已经包含了一个后退按钮,单击此按钮会使用下面的代码将XML ListModel源更改回本地文件,

searchCityModel.source = localCityUrl();

然而,在这样做时,我收到错误消息,

TypeError: Cannot read property 'city' of undefined

它基本上抱怨它试图读取Xml ListModel的值以分配给文本委托。

如何确保它只在Xml ListModel准备就绪时尝试执行此操作?我已尝试在Xml ListModel中使用onStatusChanged。

奇怪的是,它只是在从在线更改为本地时才会抱怨源更改。因此,当用户第一次在线搜索时,它不会显示任何错误。但只有当用户按下后退按钮切换到本地源时才会出现错误。

1 个答案:

答案 0 :(得分:2)

您实际上没有在ListModel中正确使用该模型,这可能会导致您的问题。您的委托应使用底层模型向委托公开的属性。通过调用searchCityModel.get(index),您没有使用绑定到ListView的模型。您的代表应该更像以下

ListView {
        id: worldList

        anchors { left: parent.left; right: parent.right }
        height: units.gu(50)
        model: searchCityModel    

        delegate: Rectangle {
            width: worldList.width
            height: 20 //This has to be hardcoded to avoid the binding loop with the MouseArea

            text: city + ", " + country
            MouseArea {
                anchors.fill: parent
                onClicked: {
                    worldList.currentIndex = index;
                }
            }
        }
    }