The setup
I have a ListView
with some general model and myDelegate
component.
ListView {
id: myListView
delegate: myDelegate
...
}
In myDelegate
component, I want to set ListView
's currentItem
. I currently do it like this:
Component {
id: myDelegate
...
MouseArea {
onClicked: myListView.currentIndex = model.index
}
}
Everything works as expected.
The issue
As commonly known, it's bad practice to use ListView
's id
inside a delegate, since there could be multiple ListView using the same delegate component. So, ListView.view attached property should be used instead.
But if I change the delegate's code like this:
Component {
id: myDelegate
...
MouseArea {
onClicked: ListView.view.currentIndex = model.index
}
}
I get a TypeError: Value is null and could not be converted to an object
.
With the following console.logs, I discovered that ListView.view
is always null. I don't understand why. Setting currentIndex
on ListView
itself fails too.
onClicked: {
console.log("ListView:", ListView)
console.log("ListView.view:", ListView.view)
console.log("ListView.currentIndex:", ListView.currentIndex)
}
...
qml: ListView: QQuickListViewAttached(0x6db0b30)
qml: ListView.view: null
qml: ListView.currentIndex: undefined
Minimal reproducible example
Qt v6.2.1
Empty Qt Quick project in Qt Creator
main.qml:
import QtQuick
import QtQuick.Window
Window {
width: 150
height: 350
visible: true
Component {
id: myDelegate
Rectangle {
color: ListView.isCurrentItem ? "pink" : "lightblue"
implicitWidth: 150
implicitHeight: 50
MouseArea {
anchors.fill: parent
onClicked: {
ListView.view.currentIndex = model.index
console.log("ListView", ListView)
console.log("ListView.view", ListView.view)
}
}
Text {
anchors.centerIn: parent
text: model.index
}
}
}
ListView {
id: myListView
anchors.fill: parent
spacing: 2
model: 6
delegate: myDelegate
}
}
CodePudding user response:
The attached properties are set in the root of the delegate so if you want to access from a child item then you must use the root as reference:
Component {
id: myDelegate
Rectangle {
id: root_delegate // <---
color: ListView.isCurrentItem ? "pink" : "lightblue"
implicitWidth: 150
implicitHeight: 50
MouseArea {
anchors.fill: parent
onClicked: {
root_delegate.ListView.view.currentIndex = model.index;
console.log("ListView", root_delegate.ListView);
console.log("ListView.view", root_delegate.ListView.view);
}
}
Text {
anchors.centerIn: parent
text: model.index
}
}
}