DevExpress GridControl Bound to Object с BindingList не обновляет элементы управления - PullRequest
0 голосов
/ 31 октября 2018

У меня есть форма с несколькими элементами управления; некоторые текстовые поля, которые связаны данными со свойствами объекта частной формы (Financial) и DevExpress GridControl, который связан данными со свойством BindingList (of Fee) (Fees) в том же финансовом объекте. Одним из свойств в Financial является свойство только для чтения, которое рассчитывает некоторые данные на основе других свойств Financial и Fees (MonthlyCosts). И финансовые, и комиссионные реализуют INotifyPropertyChanged.

Проблема, с которой я сталкиваюсь, заключается в том, что текстовое поле, привязанное к этому свойству MonthlyCosts, не обновляется при внесении изменений в GridControl. Если я изменю стоимость комиссии в GridControl, а затем изменит значение текстового поля (Margin), которое также используется в этом расчете, текстовое поле с рассчитанным значением будет обновляться только после того, как я изменил Margin.

Часть соответствующего кода показана ниже:

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))

Кажется, что все привязки данных работают нормально, за исключением случая, когда изменение сборов не приводит к изменению текстового поля Итого. Если я помещаю кнопку, которая отображает свойство Total в MessageBox, он сообщает правильное значение Total, но текстовое поле не обновляется. Похоже, что NotifyPropertyChanged на объекте Fee не распространяется через BindingList в форму, чтобы сказать ему обновить текстовое поле Total.

1 Ответ

0 голосов
/ 02 ноября 2018

Кажется, что все привязки данных работают нормально, за исключением случая, когда изменение сборов не меняет текстовое поле Всего.

В вашем коде нет ничего, что могло бы вызвать событие PropertyChanged для свойства Total. Поскольку Total является вычисляемым значением, зависящим от свойств Fees и Margin, изменения этих свойств также должны вызывать уведомление об изменении для Total.

Поскольку Fees объявлен как BindingList (Of Fee) , подписка на его ListChanged Event обеспечит средство уведомления об изменении Total из-за изменений в Fees.

Ниже приведен рабочий пример 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
...