如何处理ComboBox选择的索引更改?

时间:2009-04-23 15:38:53

标签: .net winforms combobox

我有一个包含制造商列表的ComboBox。当用户选择制造商时,下面的网格将填充所选制造商的数据。该数据可以修改。完成所有更改后,用户必须按“保存”按钮。

但是用户可能忘记按保存并从ComboBox中选择另一个制造商,网格将填充其他数据,因此之前的更改将会丢失。

因此,在选择其他制造商之前,我需要询问用户是否要保存更改。

我该怎么做?或者也许你提供另一种解决我的任务的方法(从另一个角度来看)?

10 个答案:

答案 0 :(得分:9)

以下是我们如何将ComboBox子类化以引入新的SelectedIndexChangingEvent,并可以取消更改:

    public class ComboBoxEx : ComboBox
{
    public event CancelEventHandler SelectedIndexChanging;

    [Browsable(false)]
    public int LastAcceptedSelectedIndex { get; private set; }

    public ComboBoxEx()
    {
        LastAcceptedSelectedIndex = -1;
    }

    protected void OnSelectedIndexChanging(CancelEventArgs e)
    {
        var selectedIndexChanging = SelectedIndexChanging;
        if (selectedIndexChanging != null)
            selectedIndexChanging(this, e);
    }


    protected override void OnSelectedIndexChanged(EventArgs e)
    {
        if (LastAcceptedSelectedIndex != SelectedIndex)
        {
            var cancelEventArgs = new CancelEventArgs();
            OnSelectedIndexChanging(cancelEventArgs);

            if (!cancelEventArgs.Cancel)
            {
                LastAcceptedSelectedIndex = SelectedIndex;
                base.OnSelectedIndexChanged(e);
            }
            else
                SelectedIndex = LastAcceptedSelectedIndex;
        }
    }

}

答案 1 :(得分:4)

创建2个类级变量

private bool selectionCancelled=false;
private int lastSelectedIndex=-1;

然后在SelectedIndex事件中,您可以编写如下代码

        if (!selectionCancelled)
        {
            if (MessageBox.Show("Are you sure you want to change the selection ?", this.Text, MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No)
            {
                selectionCancelled = true;
                comboBox.SelectedIndex = lastSelectedIndex;
                return;
            }

            lastSelectedIndex = comboBox.SelectedIndex;
            // Normal code of the event handler

        }
        else
        {

            selectionCancelled = false;
        }

答案 2 :(得分:3)

您应该处理ComboBox.SelectedIndexChanged事件。类似的东西:

this.ComboBox1.SelectedIndexChanged += new system.EventHandler(ComboBox1_SelectedIndexChanged);

然后只要它发生变化就会调用ComboBox1_SelectedIndexChanged(),您可以在该功能中更新制造商信息。在填充新信息之前保存旧信息。或者在保存之前提示用户是否真的想要更改它。

答案 3 :(得分:1)

Night Coder的解决方案优雅而简洁。我把它打包成了一个dll (我称之为CustomControls。)为此,创建一个新的类库并将前几个语句添加到Night Coder的解决方案中(为方便起见,这里复制)。

编译完代码后,可以将其添加为参考。我实际上将dll加载到我的Visual Studio工具窗格中。这样我就可以在设计时将控件拖到我的表单上。方便的是,新事件显示在属性列表中。

use System.ComponentModel;

use System.Windows.Forms; //this will need to be added as a reference

//your namespace will name your dll call it what you will

namespace CustomControls

Night Coder的解决方案如下:

public class ComboBoxEx : ComboBox
{
        public event CancelEventHandler SelectedIndexChanging;


    [Browsable(false)]
    public int LastAcceptedSelectedIndex { get; private set; }

    public ComboBoxEx()
    {
            LastAcceptedSelectedIndex = -1;
    }

    protected void OnSelectedIndexChanging(CancelEventArgs e)
    {
            var selectedIndexChanging = SelectedIndexChanging;
            if (selectedIndexChanging != null)
                    selectedIndexChanging(this, e);
    }


    protected override void OnSelectedIndexChanged(EventArgs e)
    {
            if (LastAcceptedSelectedIndex != SelectedIndex)
            {
                    var cancelEventArgs = new CancelEventArgs();
                    OnSelectedIndexChanging(cancelEventArgs);

                    if (!cancelEventArgs.Cancel)
                    {
                            LastAcceptedSelectedIndex = SelectedIndex;
                            base.OnSelectedIndexChanged(e);
                    }
                    else
                            SelectedIndex = LastAcceptedSelectedIndex;
            }
    }
}

答案 4 :(得分:1)

跟踪未保存更改的简便方法。

加载任何原始值后,禁用“保存”按钮。

当用户尝试离开时,请检查“保存”按钮是否已启用。

根据需要启用或禁用“保存”按钮。

答案 5 :(得分:1)

我知道这是一个较旧的问题,但我想我会添加我使用的方法。我不确定它是否更好。 IndexChanging中应该有ComboBox个事件可以取消。

该解决方案是@ AftabAhmedKalhoro和@ jeffamaphone的帖子的组合,但改为使用Tag属性。

我不想对ComboBox进行子类化,或者在表单中有任何额外的私有变量。但是有些人可能不喜欢Tag属性,因为如果你不习惯使用它,它会被隐藏(从VB6中遗留下来的那种)。

Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    ComboBox1.Items.Add("Item1")
    ComboBox1.Items.Add("Item2")
    ComboBox1.Items.Add("Item3")
    ComboBox1.Items.Add("Item4")
    ' Load Value from database or whatever and set the value or index.
    ComboBox1.SelectedIndex = 0
    ComboBox1.Tag = ComboBox1.SelectedIndex

    ' I add the handler at the end because I don't want it to fire during loading the form.
    AddHandler ComboBox1.SelectedIndexChanged, New EventHandler(AddressOf ComboBox1_SelectedIndexChanged)
End Sub

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
    If (ComboBox1.Tag <> ComboBox1.SelectedIndex) Then
        If MessageBox.Show("Warning! You are changing the index." & vbCrLf & _
                           "Do you wish to continue?", _
                           "Changing Index", _
                           MessageBoxButtons.YesNo, _
                           MessageBoxIcon.Warning) = Windows.Forms.DialogResult.Yes Then
            ComboBox1.Tag = ComboBox1.SelectedIndex
            ' Do Something.
        Else
            ComboBox1.SelectedIndex = ComboBox1.Tag
        End If
    End If
End Sub

请注意,重置SelectedIndex会导致事件再次在此行中触发:

ComboBox1.SelectedIndex = ComboBox1.Tag

答案 6 :(得分:0)

如果您想知道如何在选择更改时收到通知,您可以订阅ComboBox.SelectedIndexChanged事件。

如果您想为用户提供保存选项,只有在某些内容发生变化并且忘记了以便保存更改时,您需要跟踪这些其他字段何时发生变化。这可以通过维护一个布尔值来实现,该值在用户编辑任何字段时设置为true。发生上述事件时,请在决定是否提供保存选项之前检查此值。

答案 7 :(得分:0)

这里最好的做法是将ComboBox(与其他字段同样)中输入的数据与已存储的数据(无论是DataSet,列表对象等)进行比较并检查任何差异。这样,如果用户从ComboBox中选择另一个项目,然后将其更改回原始项目,则程序会识别出数据仍然已被修改。 (例如,处理SelectionChangeCommited事件并将布尔值设置为true,将不允许检测到这种情况,并且还会稍微难以实现。)在这种情况下,最简单的最优雅的方法似乎也提供了最好的功能。

答案 8 :(得分:0)

出色的夜间编码器。您的代码完美无缺。

谢谢!

对于使用VB.NET编写的开发人员,您可以进行翻译:

Imports System.ComponentModel

Public Class ComboBoxEx
  Inherits ComboBox

  Private pLastAcceptedSelectedIndex As Integer

  Public Event SelectedIndexChanging As CancelEventHandler

  Public Property LastAcceptedSelectedIndex() As Integer
    Get
      Return pLastAcceptedSelectedIndex
    End Get
    Set(ByVal value As Integer)
      pLastAcceptedSelectedIndex = value
    End Set
  End Property

  Public Sub New()
    LastAcceptedSelectedIndex = -1
  End Sub

  Protected Sub OnSelectedIndexChanging(ByVal e As CancelEventArgs)
    RaiseEvent SelectedIndexChanging(Me, e)
  End Sub

  Protected Overrides Sub OnSelectedIndexChanged(ByVal e As System.EventArgs)
    If LastAcceptedSelectedIndex <> SelectedIndex Then
      Dim cancelEventArgs As CancelEventArgs

      cancelEventArgs = New CancelEventArgs()
      OnSelectedIndexChanging(cancelEventArgs)

      If Not cancelEventArgs.Cancel Then
        LastAcceptedSelectedIndex = SelectedIndex
        MyBase.OnSelectedIndexChanged(e)
      Else
        SelectedIndex = LastAcceptedSelectedIndex
      End If
    End If
  End Sub
End Class

答案 9 :(得分:-2)

ComboBox提供了一个名为SelectedIndexChanged的事件。 Property SelectedIndex更改时会引发此事件,因此您必须处理该事件,每当用户想要更改组合的索引时,如果用户尚未保存更改,请让他这样做。