使用 BindingList 绑定到对象的 DevExpress GridControl 不更新控件

DevExpress GridControl Bound to Object with a BindingList isn't updating controls

我有一个带有一些控件的表单;一些数据绑定到私有表单对象属性 (Financial) 的文本框和数据绑定到同一财务对象上的 BindingList(of Fee) (Fees) 属性 的 DevExpress GridControl。 Financial 的属性之一是只读 属性,它根据 Financial 和 Fees (MonthlyCosts) 的其他属性计算一些数据。 Financial 和 Fee 都实现了 INotifyPropertyChanged。

我遇到的问题是,当对 GridControl 进行更改时,绑定到 MonthlyCosts 属性 的文本框不会更新。如果我在 GridControl 中更改费用成本,然后更改也在该计算中使用的文本框值(保证金),具有计算值的文本框将仅在我更改保证金后更新。

部分相关代码如下:

Public Class Financial
    Inherits BindableBase ' helper for INotifyPropertyChanged

    Public Property Margin As Decimal
        Get
            return _margin
        End Get
        Set
            SetProperty() ' INotifyPropertyChanged stuff
        End Set
    End Property

    Public ReadOnly Property Fees As BindingList(Of Fee)

    Public ReadOnly Property Total as Decimal
        Get
            return Fees.Sum(Function(fee) fee.Amount) / (1 - Margin)
        End Get
    End Property
End Class

Public Class Fee
    Inherits BindableBase ' helper for INotifyPropertyChanged

    Public Property Amount as Decimal
End Class

形式为:

' Setup the databindings
Margin.DataBindings.Add("EditValue", Financial, NameOf(Financial.Margin))
FeeGrid.DataBindings.Add("DataSource", Financial, NameOf(Financial.Fees))
Total.DataBindings.Add("EditValue", Financial, NameOf(Financial.Total))

数据绑定似乎都工作正常,除非更改费用不会更改总计文本框。如果我在 MessageBox 中放置一个弹出总计 属性 的按钮,它会报告正确的总计,但文本框不会更新。 Fee 对象上的 NotifyPropertyChanged 似乎没有通过 BindingList 向上传播到 Form 以告诉它刷新 Total 文本框。

The databindings all seem to work fine, except in the case of changing the Fees doesn't change the Total textbox.

您的代码中没有显示会引发总计 属性 的 PropertyChanged 事件。由于 Total 是依赖于属性 FeesMargin 的计算值,对这些属性的更改也应该引发 Total.

的更改通知

由于 Fees 被声明为 BindingList(Of Fee), subscribing to its ListChanged Event 将提供一种通知由于 Fees.

中的更改而对 Total 进行更改的方法

以下是一个与您发布的内容类似的 WinForm 示例,但它仅使用常用控件(TextBox、DataGridView 和 Label)。

Public Class BindableBase : Implements INotifyPropertyChanged
    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Protected Sub RaisePropertyChanged(<CallerMemberName> Optional PropName As String = Nothing)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(PropName))
    End Sub
End Class

Public Class Financial : Inherits BindableBase

    Public _margin As Decimal

    Public Sub New()
        Fees = New BindingList(Of Fee)
        AddHandler Fees.ListChanged, AddressOf Fees_Changed
    End Sub

    Private Sub Fees_Changed(sender As Object, e As ListChangedEventArgs)
        NotifyTotalChanged()
    End Sub

    Private Sub NotifyTotalChanged()
        RaisePropertyChanged(NameOf(Me.Total))
    End Sub

    Public Property Margin As Decimal
        Get
            Return _margin
        End Get
        Set(ByVal value As Decimal)
            If value <> _margin Then
                _margin = value
                RaisePropertyChanged()
                NotifyTotalChanged() ' Margin affects Total
            End If
        End Set
    End Property

    Public ReadOnly Property Fees As BindingList(Of Fee)

    Public ReadOnly Property Total As Decimal
        Get
            Return Fees.Sum(Function(fee) fee.Amount) / (1 - Margin)
        End Get
    End Property

End Class

Public Class Fee : Inherits BindableBase

    Private _Amount As Decimal
    Public Property Amount As Decimal
        Get
            Return _Amount
        End Get
        Set(value As Decimal)
            If value <> _Amount Then
                _Amount = value
                RaisePropertyChanged()
            End If
        End Set
    End Property
End Class

用法示例:

Public Class Form1
    Private Financial As New Financial
    Protected Overrides Sub OnLoad(e As EventArgs)
        MyBase.OnLoad(e)
        SetFinancialBindings()
    End Sub

    Private Sub SetFinancialBindings()
        Margin.DataBindings.Add("Text", Me.Financial, NameOf(Me.Margin))
        FeeGrid.DataBindings.Add("DataSource", Me.Financial, NameOf(Me.Financial.Fees))
        Total.DataBindings.Add("Text", Me.Financial, NameOf(Me.Financial.Total))
    End Sub
End Class