selecting delegates depending on property

2019-05-14 10:53发布

问题:

I have a listview where I want to use either a defaultDelegate or a customDelegate depending on the value of a property. So far I've tried using a component to load the different delegates:

 Component{
    id: delegate
    Loader {
        sourceComponent: type == 3 ? customDelegate : defaultDelegate
    }
}

However, I can't access the properties I have in my model from the two delegates I have. I have the following error:

ReferenceError: name is not defined

Here is the model I use:

ListModel {
     id: test
     ListElement {
         name: "Bill"
         team: "554"
         type: 2
     }
     ListElement {
         name: "John"
         team: "555"
         type: 3
     }
     ListElement {
         name: "Sam"
         team: "556"
         type: 1
     }
 }

Does anyone Have any idea, what I am doing wrong here?

回答1:

It is, of course, a context problem. In your code, the name, team and type context properties inserted by the ListView into delegate's context is inaccessible to the components inside your delegates, as the Loader uses the creation context of customDelegate and defaultDelegate as the parent context when instantiating them, and name, team and type do not refer to anything withing that context chain. One solution is to explicitly set the required information as a property of the Loader (this works because the Loader sets itself as the context object for the component it is loading).

Following a working example:

ListModel {
     id: testModel
     ListElement {
         name: "Bill"
         team: "554"
         type: 2
     }
     ListElement {
         name: "John"
         team: "555"
         type: 3
     }
     ListElement {
         name: "Sam"
         team: "556"
         type: 1
     }
 }

ListView {
    anchors.fill: parent
    model: testModel

    delegate: myDelegate
}

Component {
    id: myDelegate // yourDelegate
    Loader {
        property string modelName: model.name
        property string modelTeam: model.team
        property int modelType: model.type
        sourceComponent: modelType === 3 ? colonDelegate : semicolonDelegate
    }
}

Component {
    id: colonDelegate
    Text { text: modelName + ": " + modelTeam }
}

Component {
    id: semicolonDelegate
    Text { text: modelName + "; " + modelTeam }
}

For further reading and improvements I highly recommend you to read this.



标签: qt delegates qml