如何创建一个属性,该属性对列表项进行汇总,并在列表项的值更改时进行更新?

时间:2019-09-02 16:36:09

标签: tornadofx

我尝试显示房屋的成本,该成本应根据房屋中的房间成本进行计算,并应显示在ListView中,但是当我更改房屋时,我无法让HouseListFragment正确显示更改房间的费用。

我试图通过Bindings.createIntegerBinding和带有提取器的ObservableArray来实现这一点...

class House(name: String = "", rooms: MutableList<Room> = mutableListOf()) : NamedComponent(name)
{
    val roomsProperty = SimpleListProperty<Room>(this, "rooms ", rooms.asObservable())
    var rooms: ObservableList<Room> by roomsProperty

    val costProperty = SimpleIntegerProperty(this, "cost", 0)
    var cost by costProperty

    var roomsCostChanged: ObservableList<IntegerProperty> = FXCollections.observableArrayList<IntegerProperty> { p -> arrayOf<Observable>(p) }
    val totalProperty = Bindings.createIntegerBinding(
            Callable { roomsCostChanged.stream().mapToInt { it.value }.sum() }, roomsCostChanged).toProperty()

    init
    {
        updateRoomCostListenerList()
        roomsProperty.onChange { _: ListChangeListener.Change<out Room> ->
            run {
                updateRoomCostListenerList()
            }
        }
    }

    private fun updateRoomCostListenerList()
    {
        roomsCostChanged.clear()
        roomsProperty.forEach(Consumer { roomsCostChanged.add(it.costProperty) })
    }
}
class HouseModel : ItemViewModel<House>()
{
    val name = bind(House::nameProperty, autocommit = true)
    val rooms = bind(House::roomsProperty, autocommit = true)
    val cost = bind(House::totalProperty, autocommit = true)
}
class HouseFragment : ListCellFragment<House>()
{
    private val controller by inject<QuotationController>()
    private val house = HouseModel().bindTo(this)

    override val root = vbox {
        borderpane {
            removeWhen { editingProperty }
            top = hbox {
                label(house.name) {
                    setId(Styles.contentLabel)
                }
            }
            center = hbox {
                label {
                    house.rooms.onChange {
                        text = "${it?.size} ${messages["rooms_in_this_house"]}"
                    }
                }
            }
            right = label {
                house.cost.onChange {
                    text = "${it?.get()} € total costs"
                }
            }

        }

...

编辑:

通过更改init块来添加onChange侦听器和初始设置可以解决问题,最后不需要事件。对此,奥皮宁仍然表示赞赏...

init
    {
        roomsProperty.onChange { _: ObservableList<Room>? -> updateRoomCostListenerList() }
        totalProperty.onChange { cost = it }

        updateRoomCostListenerList()
        cost = totalProperty.get()
    }

0 个答案:

没有答案