Выражение столбца данных с переменной - PullRequest
0 голосов
/ 01 июля 2019

У меня следующий код, и он не работает, а стоимость расчета равна нулю. В чем здесь ошибка?

.Columns.Add("Total", Type.GetType("System.Int32"))
.Columns("Total").Expression = "200 * " & FxRate.ToString

FxRate является публичной переменной.

Ответы [ 2 ]

1 голос
/ 02 июля 2019

при изменении FxRate поля Total должны автоматически обновляться.

DataColumn.Expression не предоставляет способ ссылки на внешние переменные.Однако вы можете обновить выражение в любое время.

Вам нужно будет вызвать метод обновления, когда FxRate изменится.Если FxRate является свойством, вы можете вызвать метод update из его метода установки.

Изменения в выражении не будут автоматически отражаться в связанном элементе управления.Метод обновления также должен указать привязкам для обновления.Если вы выполняете привязку через экземпляр BindingSource, вызовите его метод ResetBindings(False).Если вы выполняете привязку непосредственно к методу DataTable, a more complex method would be to obtain the DataTable 's CurrencyManager and call its Refresh`.

Предполагая, что переменная DataTable имеет имя dt, следующий код получит CurrencyManager;Me относится к содержащему Form.

Dim mngr As CurrencyManager = CType(Me.BindingContext.Item(dt), CurrencyManager)
mngr.Refresh()

Редактировать: рабочий пример с использованием BindingSource, как было запрошено в комментариях.

Вновый проект WinForm, замените содержимое Form1.vb следующим кодом (все элементы управления создаются этим кодом - без поддержки дизайнера).

Код создает: TextBox для изменения поля «Количество», Label для отображения поля «Всего», NumericUpDown для изменения значения свойства FxRateи две кнопки, чтобы разрешить навигацию по записям в DataTable.

. DataTable имеет три записи. Запись состоит из двух полей «Количество» и «Всего». «Всего» будет вычислено какпроизведение свойства формы FxRate и поля «Количество», устанавливая свойство Expression столбца «Количество» при каждом изменении FxRate.

Public Class Form1
  Inherits Form

  Private tbInput As TextBox
  Private lblTotal As Label
  Private nudFxRate As NumericUpDown
  Private btnNext As Button
  Private btnPrevious As Button

  Private bs As BindingSource
  Private _FxRate As Int32
  Private dt As DataTable

  Public Sub New()
    MyBase.New()
    SetupControls()
    dt = New DemoTable ' create a preconfigured DataTable
    bs = New BindingSource(dt, Nothing)
    SetBindings()
    FxRate = 5
    AttachControlEventHandlers()
  End Sub

  Public Property FxRate As Int32
    Get
      Return _FxRate
    End Get
    Set(value As Int32)
      If value <> _FxRate Then
        _FxRate = value
        UpdateTotalExpression() ' only update the Expression if the value changes
      End If
    End Set
  End Property

  Private Sub UpdateTotalExpression()
    ' Change the expression to reflect the current value of FxRate
    Dim totalColumn As DataColumn = dt.Columns("Total")
    totalColumn.Expression = $"[Quantity] * {FxRate}"
    ' Expression changes do not notify the BindingSource of value changes
    ' so tell the BindingSource to reload all values
    bs.ResetBindings(False)
  End Sub

  Private Sub tbInput_KeyPress(sender As Object, e As KeyPressEventArgs)
    If e.KeyChar = Convert.ToChar(Keys.Enter) Then
      Me.Validate()     ' force tbInput to Validate
      e.Handled = True  ' eat the enter key
    End If
  End Sub

  Private Sub tbInput_Validated(sender As Object, e As EventArgs)
    ' if tbInput successfully validated, push the values in the BindingSource to the DataTable
    bs.EndEdit() ' push the editted value to the DataTable, causing Total to update
  End Sub

  Private Sub SetBindings()
    ' Update BindingSource once tbInput Validates successfully
    tbInput.DataBindings.Add("Text", bs, "Quantity", True, DataSourceUpdateMode.OnValidation)
    ' lblTotal never updates the BindingSource
    lblTotal.DataBindings.Add("Text", bs, "Total", True, DataSourceUpdateMode.Never)
    ' nudFxRate updates the FxRate property
    nudFxRate.DataBindings.Add("Value", Me, "FxRate", True, DataSourceUpdateMode.OnPropertyChanged)
  End Sub

  Private Sub SetupControls()
    tbInput = New System.Windows.Forms.TextBox()
    lblTotal = New System.Windows.Forms.Label()
    nudFxRate = New System.Windows.Forms.NumericUpDown()
    btnNext = New System.Windows.Forms.Button()
    btnPrevious = New System.Windows.Forms.Button()
    CType(nudFxRate, System.ComponentModel.ISupportInitialize).BeginInit()
    SuspendLayout()
    '
    'tbInput
    '
    tbInput.Location = New System.Drawing.Point(27, 40)
    tbInput.Name = "tbInput"
    tbInput.Size = New System.Drawing.Size(100, 22)
    tbInput.TabIndex = 0
    '
    'lblTotal
    '
    lblTotal.AutoSize = False
    lblTotal.BackColor = Color.Yellow
    lblTotal.Location = New System.Drawing.Point(299, 42)
    lblTotal.Name = "lblTotal"
    lblTotal.Size = New System.Drawing.Size(100, 17)
    lblTotal.TabIndex = 1
    lblTotal.Text = "0"
    '
    'nudFxRate
    '
    nudFxRate.Location = New System.Drawing.Point(28, 94)
    nudFxRate.Name = "nudFxRate"
    nudFxRate.Size = New System.Drawing.Size(120, 22)
    nudFxRate.TabIndex = 3
    nudFxRate.Value = 5
    '
    'btnNext
    '
    btnNext.Location = New System.Drawing.Point(27, 136)
    btnNext.Name = "btnNext"
    btnNext.Size = New System.Drawing.Size(75, 23)
    btnNext.TabIndex = 4
    btnNext.Text = "Next"
    btnNext.UseVisualStyleBackColor = True
    '
    'btnPrevious
    '
    btnPrevious.Location = New System.Drawing.Point(28, 171)
    btnPrevious.Name = "btnPrevious"
    btnPrevious.Size = New System.Drawing.Size(75, 23)
    btnPrevious.TabIndex = 5
    btnPrevious.Text = "Previous"
    btnPrevious.UseVisualStyleBackColor = True
    '
    'Form1
    '
    AutoScaleDimensions = New System.Drawing.SizeF(8.0!, 16.0!)
    AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
    ClientSize = New System.Drawing.Size(800, 450)
    Controls.Add(btnPrevious)
    Controls.Add(btnNext)
    Controls.Add(nudFxRate)
    Controls.Add(lblTotal)
    Controls.Add(tbInput)
    Name = "Form1"
    Text = "Form1"
    CType(nudFxRate, System.ComponentModel.ISupportInitialize).EndInit()
    ResumeLayout(False)
    PerformLayout()

  End Sub

  Private Sub AttachControlEventHandlers()
    AddHandler btnNext.Click, Sub() bs.MoveNext()  ' move to next record in bindingsource
    AddHandler btnPrevious.Click, Sub() bs.MovePrevious() ' move to previous record in bindingsource
    AddHandler tbInput.KeyPress, AddressOf tbInput_KeyPress ' allow enter key to validate textbox
    AddHandler tbInput.Validated, AddressOf tbInput_Validated ' update bindingsource on validation
  End Sub

  Private Class DemoTable : Inherits DataTable
    Public Sub New()
      Columns.Add("Quantity", GetType(Int32))
      Columns.Add("Total", GetType(Int32))
      Rows.Add(New Object() {10})
      Rows.Add(New Object() {20})
      Rows.Add(New Object() {30})
    End Sub
  End Class
End Class
0 голосов
/ 02 июля 2019

Добавьте столбец FxRate.Измените выражение для столбца «Итого» на "200 * FxRate", и значение столбца «Итого» будет автоматически установлено на основе любого значения, установленного для FxRate.

.Columns.Add("FxRate", Type.GetType("System.Int32"))

.Columns.Add("Total", Type.GetType("System.Int32"))
.Columns("Total").Expression = "200 * FxRate"

' Example of setting FxRate in row 0.
' (Assuming row 0 exists.)
.Rows(0).Item("FxRate") = 3
...