如何正确地将模型中的 属性 绑定到委托中手工制作的项目中的 属性?

How to correctly bind a property from model to property in hand-made Item in delegate?

我想为任意模型的 ListView 创建一个编辑委托。 在委托中,我想使用我自己的 NeatInput 继承自 TextInputNeatInput 声明自己的 属性 realValue,将 text 绑定到 realValue,并且在 textChanged 信号改变 realValue 时使其成为双向的。这按预期工作:

/*NeatInput.qml*/

import QtQuick 2.0
TextInput {
    width: 50
    property real realValue: 0.0
    text: realValue * 2
    onTextChanged: {
        realValue = Number.fromLocaleString(locale, text) / 2
    }
}

现在,它仅用作 ListView 中的委托,在模型的 someValue 上绑定 realValue,并且出于编辑目的,写入 someValuerealValueChanged:

/*main.qml*/
import QtQuick 2.12
import QtQuick.Controls 2.12
  
ApplicationWindow {
    width: 500
    height: 500
    visible: true
    
    ListView {
        id: view
        model: ListModel {
            ListElement {
                someValue: 50
            }
        }
        anchors.fill: parent
        delegate: Row {
            NeatInput {
                realValue: someValue
                onRealValueChanged: someValue = realValue
            }

            SpinBox {
                value: someValue
                onValueChanged: someValue = value
            }
            Text {
                width: 50
                text: someValue
            }
        }
    }
}

Text 用于简单阅读,SpinBox 用于 read/write with standard Item.

但这并不像我预期的那样有效:

因此,someValueNeatInput 的绑定在某种程度上被破坏了,但是写入了工作。 如果我从 NeatInput.qml 中删除信号绑定 onTextChanged,那么:

我应该怎么做才能让所有读者都能看到两位编辑的更新?

一般的经验法则是:赋值中断绑定。每当您这样做时:

    onTextChanged: {
        realValue = Number.fromLocaleString(locale, text) / 2
    }

它破坏了您在此处创建的绑定:

    realValue: someValue

所以第一次 text 更改时,realValue 将停止侦听对 someValue 的更新。

Two-way 绑定总是很棘手,因为它们会变成循环。我玩了一分钟你的代码并通过这样做让它工作:

    ListView {
        id: view
        model: ListModel {
            ListElement {
                someValue: 50
            }
        }
        anchors.fill: parent
        delegate: Row {
            NeatInput {
                realValue: someValue
                onRealValueChanged: someValue = realValue

                property real someValueCopy: someValue
                onSomeValueCopyChanged:
                {
                    realValue = someValueCopy;
                }
            }

            SpinBox {
                value: someValue
                onValueChanged: someValue = value
            }
            Text {
                width: 50
                text: someValue
            }
        }
    }