【问题标题】:Control values in numeric control数值控制中的控制值
【发布时间】:2016-02-29 16:49:13
【问题描述】:

可能很容易,但我不知道如何实现这一目标。我的表单上有 3 个数字控件。那里的值可能是1,2 or 3。假设这三个值中的每一个都只能在其中一个控件中出现一次。所以假设我有

IntInputVariation1.value = 1
IntInputVariation2.value = 2
IntInputVariation3.value = 3

现在,如果有人将其中一个值更改为 IntInputVariation2.value 到 3,那么 IntInputVariation3.value 必须为 2。

希望你明白我的意思。

当表单正在加载时,所有控件都从 1 设置为 3,如下所示:

IntInputVariation1.value = 1
IntInputVariation2.value = 2
IntInputVariation3.value = 3

此时用户可以更改它...

到目前为止,我这样做了,但仍然有问题..你能帮忙吗?

我试图像这样保存我的控件的第一个状态:

Private Class VariationPositionValues
        Public Shared First As String = "IntInputVariation1"
        Public Shared Second As String = "IntInputVariation2"
        Public Shared Third As String = "IntInputVariation3"
    End Class

然后下面的处理程序方法我关联到所有那些控制 ValueChanged 事件:

 Private Sub IntInputVariation_ValueChanged(sender As Object, e As EventArgs)



        Dim inputNumbControl As DevComponents.Editors.IntegerInput = CType(sender, DevComponents.Editors.IntegerInput)
        Dim NewValue As Integer = inputNumbControl.Value


        Select Case inputNumbControl.Name
            Case "IntInputVariation1"

                If IntInputVariation2.Value = NewValue Then
                    IntInputVariation2.Value = 1
                    VariationPositionValues.IntInputVariation1 = IntInputVariation1.Value
                    VariationPositionValues.IntInputVariation2 = IntInputVariation2.Value
                End If
                If IntInputVariation3.Value = NewValue Then
                    IntInputVariation3.Value = VariationPositionValues.IntInputVariation1
                    VariationPositionValues.IntInputVariation1 = IntInputVariation1.Value
                    VariationPositionValues.IntInputVariation3 = IntInputVariation3.Value
                End If

            Case "IntInputVariation2"
                If IntInputVariation1.Value = NewValue Then
                    IntInputVariation1.Value = VariationPositionValues.IntInputVariation2
                    VariationPositionValues.IntInputVariation2 = IntInputVariation2.Value
                    VariationPositionValues.IntInputVariation1 = IntInputVariation1.Value
                End If
                If IntInputVariation3.Value = NewValue Then
                    IntInputVariation3.Value = VariationPositionValues.IntInputVariation2
                    VariationPositionValues.IntInputVariation2 = IntInputVariation2.Value
                    VariationPositionValues.IntInputVariation3 = IntInputVariation3.Value
                End If

            Case "IntInputVariation3"
                If IntInputVariation1.Value = NewValue Then
                    IntInputVariation1.Value = VariationPositionValues.IntInputVariation3
                    VariationPositionValues.IntInputVariation3 = IntInputVariation3.Value
                    VariationPositionValues.IntInputVariation1 = IntInputVariation1.Value
                End If
                If IntInputVariation2.Value = NewValue Then
                    IntInputVariation2.Value = VariationPositionValues.IntInputVariation3
                    VariationPositionValues.IntInputVariation3 = IntInputVariation3.Value
                    VariationPositionValues.IntInputVariation2 = IntInputVariation2.Value
                End If
        End Select
    End Sub

进一步讨论:

  Select Case variationCount
                Case 1
                    nums = Enumerable.Range(1, 1).ToArray
                    nuds = {IntInputVariation1}
                Case 2
                    nums = Enumerable.Range(1, 2).ToArray
                    nuds = {IntInputVariation1, IntInputVariation2}
                Case 3
                    nums = Enumerable.Range(1, 3).ToArray
                    nuds = {IntInputVariation1, IntInputVariation2, IntInputVariation3}
            End Select

            ignore = False

那么当代码在第二次尝试访问事件时:

If ignore Then Exit Sub

然后得到这个错误:System.IndexOutOfRangeException

Plutonix 检查的有效解决方案:

在表单加载时得到这个:

 variationCount = BusinessLayer.SubKategorie_Variation.GetVariationCountBySubKategorie(AdvTreeSubKategories.SelectedValue)


        Select Case variationCount
            Case 1
                IntInputVariation1.MaxValue = 1

                nums = Enumerable.Range(1, 1).ToArray
                nuds = {IntInputVariation1}
            Case 2
                IntInputVariation1.MaxValue = 2
                IntInputVariation2.MaxValue = 2

                nums = Enumerable.Range(1, 2).ToArray
                nuds = {IntInputVariation1, IntInputVariation2}
            Case 3
                IntInputVariation1.MaxValue = 3
                IntInputVariation2.MaxValue = 3
                IntInputVariation3.MaxValue = 3

                nums = Enumerable.Range(1, 3).ToArray
                nuds = {IntInputVariation1, IntInputVariation2, IntInputVariation3}
        End Select

        ignore = False

后来我得到了这个:

  If ignore Then Exit Sub

        ' dont do this while doing this ;)
        ignore = True

        '--Whho called
        Dim nud = CType(sender, DevComponents.Editors.IntegerInput)
        '--Other ctls, vals, remove the one the user changed
        Dim otherVals = nums.Except(New Int32() {nud.Value}).ToArray
        Dim others = nuds.Except(New DevComponents.Editors.IntegerInput() {nud}).ToArray

        ' set the first
        others(0).Value = otherVals(0)
        otherVals = otherVals.Except(New Int32() {others(0).Value}).ToArray
        If variationCount > 2 Then others(1).Value = otherVals(0)

        ignore = False

【问题讨论】:

  • 真的只有3个值吗?
  • 是的,我认为到目前为止我找不到非常简单的方法。这 3 个数字中的一个数字只能在其中一个控件中出现一次。如果我可以在 ValueChanged 事件中获得旧值但没有,会更容易。
  • 在我的脑海中,你想在改变之前获取改变的值(也许是 focus() 事件?)并保存它,然后在改变时,通过其他两个并找到等于新值的那个,并将其更改为已更改值的先前值。我想这样就可以了。

标签: .net vb.net


【解决方案1】:

您可能遇到了由于您的代码以及用户更改值而触发该事件的问题?这使用标准的NumericUpDown 控件 - 事件等可能会有所不同。

' form level vars: 
Private ignore As Boolean = True
Private nuds As NumericUpDown()
Private nums As Int32() 

在表单加载中,无论有多少设置:

variationCount = 3

nuds = {nud1, nud2, nud3}.Take(variationCount).ToArray()
nums = Enumerable.Range(1, variationCount).ToArray()

ignore = False            ' at the end

忽略标志是为了让您可以忽略由于 NET 构建表单而导致的事件。设置值时也需要它。

Private Sub nud3_ValueChanged(sender As Object, 
          e As EventArgs) Handles nud3.ValueChanged, nud1.ValueChanged, nud2.ValueChanged
    If ignore Then Exit Sub

    ' dont do this while doing this ;)
    ignore = True

    ' who called
    Dim nud = CType(sender, NumericUpDown)
    ' other ctls, vals, remove the one the user changed
    Dim otherVals = nums.Except(New Int32() {nud.Value}).ToArray
    Dim others = nuds.Except(New NumericUpDown() {nud}).ToArray

    ' set the first
    others(0).Value = otherVals(0)
    otherVals = otherVals.Except(New Int32() {others(0).Value}).ToArray

    If variationCount > 2 Then others(1).Value = otherVals(0)

    ignore = False
End Sub

它可能会不必要地更改其中一个,仅用 3 个很难分辨,并且没有 OldValue 可以通过。

【讨论】:

  • 我认为您只需更改 nuds = {nud1, nud2, nud3} 以仅存储您正在使用的内容。代码并没有真正绑定到 三个 控件。好吧,也改变int数组
  • 更改 int 数组也被硬编码为三个
  • If variationCount > 2 Then others(1).Value = otherVals(0) - 也在看其他东西。还要确保只连接了 2 个事件处理程序
  • 当您手动更改其中一个的值时,它将再次触发事件 - 您不想处理这些事件,否则您将获得无穷无尽的它们。因此,当该事件代码正在运行时,忽略标志会阻止处理其他更改事件。您可以稍微缩短设置代码 - 不过这并不重要。我也在尝试实现史蒂夫的想法——虽然很难捕捉到 OldValue
  • 我让史蒂夫工作。由于 ValueChanged 事件中的代码更改了值,它再次触发事件。摆脱ignore,您将看到在表单加载并设置值时触发的事件,然后在事件中的代码运行时再次触发
【解决方案2】:

所以我读了你的代码并想出了这个:

Public Class Form1

    Private _PreviousValues As New Dictionary(Of NumericUpDown, Integer)  
    Private _bIgnoreChange As Boolean = True

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()
        InitValues()
        SetPreviousVars()
        _bIgnoreChange = False
        ' Add any initialization after the InitializeComponent() call.

    End Sub
    Private Sub IntInputVariation_ValueChanged(sender As Object, e As EventArgs) Handles IntInputVariation1.ValueChanged, IntInputVariation2.ValueChanged, IntInputVariation3.ValueChanged

        If Not _bIgnoreChange Then
            CheckForSwapValue(DirectCast(sender, NumericUpDown), IntInputVariation1)
            CheckForSwapValue(DirectCast(sender, NumericUpDown), IntInputVariation2)
            CheckForSwapValue(DirectCast(sender, NumericUpDown), IntInputVariation3)
        End If

        SetPreviousVars()

    End Sub

    Private Sub CheckForSwapValue(changedNUD As NumericUpDown, testNUD As NumericUpDown)

        If changedNUD IsNot testNUD AndAlso changedNUD.Value = testNUD.Value Then
            _bIgnoreChange = True
            testNUD.Value = _PreviousValues(changedNUD)
            _bIgnoreChange = False
        End If

    End Sub


    Private Sub InitValues()
        IntInputVariation1.Value = 1
        IntInputVariation2.Value = 2
        IntInputVariation3.Value = 3
    End Sub

    Private Sub SetPreviousVars()
        _PreviousValues(IntInputVariation1) = CInt(IntInputVariation1.Value)
        _PreviousValues(IntInputVariation2) = CInt(IntInputVariation2.Value)
        _PreviousValues(IntInputVariation3) = CInt(IntInputVariation3.Value)
    End Sub
End Class

我觉得你正在做的事情没有必要使用共享/静态变量。如果您要以这种方式跟踪旧值,则只需要一个类级别的变量。

当然,所有这些代码都是假设您使用的是 winforms 和 NumericUpDown 控件,但通过更改控件类型,它仍然适用于其他控件和 WPF 中。

【讨论】:

    猜你喜欢
    • 2015-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 2014-04-18
    相关资源
    最近更新 更多