【问题标题】:`SelectedIndexChanged` fires event when I set dataset of a different combobox当我设置不同组合框的数据集时,`SelectedIndexChanged` 会触发事件
【发布时间】:2019-01-28 20:27:26
【问题描述】:

这是来自 Windows 窗体中的 Windows Mobile 6.5(.net 精简版)的问题。我创建了一个包含两个用户控件的表单,每个控件都包含一个组合框。
当我加载第二个用户控件时,我填充组合框并触发第一个用户控件的组合框的_SelectedIndexChanged。 此错误仅在第一个用户控件中有控件数据网格时发生。 如果你删除数据网格,所有事件都是正确的。

 public partial class Form1 : Form
{
    static void Main(string[] args)
    {
        Application.Run(new Form1());
    }

    private UserControl1 userControl1 = null;
    private UserControl2 userControl2 = null;

    public Form1()
    {
        InitializeComponent();
        InitializeUserControl();
    }

    private void InitializeUserControl()
    {
        InitiliazeTab1();
        InitiliazeTab2();
    }

    private void InitiliazeTab1()
    {
        userControl1 = new UserControl1();
        userControl1.Dock = DockStyle.Fill;

        TabPage oTabpage1 = new TabPage();
        oTabpage1.Name = "tabSeleccionTipo1";
        oTabpage1.Text = "Tipo1 ";
        oTabpage1.Controls.Add(userControl1);
        tabControl1.TabPages.Add(oTabpage1);

        userControl1.LoadComponent();
    }

    private void InitiliazeTab2()
    {
        userControl2 = new UserControl2();
        userControl2.Dock = DockStyle.Fill;

        TabPage oTabpage2 = new TabPage();
        oTabpage2.Name = "tabSeleccionTipo2";
        oTabpage2.Text = "Tipo2 ";
        oTabpage2.Controls.Add(userControl2);
        tabControl1.TabPages.Add(oTabpage2);

        userControl2.LoadComponent();
    }
}

partial class Form1
{
    /// <summary>
    /// Variable del diseñador requerida.
    /// </summary>
    private System.ComponentModel.IContainer components = null;
    private System.Windows.Forms.MainMenu mainMenu1;

    /// <summary>
    /// Limpiar los recursos que se estén usando.
    /// </summary>
    /// <param name="disposing">true si los recursos administrados se deben eliminar; en caso contrario, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Código generado por el Diseñador de Windows Forms

    /// <summary>
    /// Método necesario para admitir el Diseñador. No se puede modificar
    /// el contenido del método con el editor de código.
    /// </summary>
    private void InitializeComponent()
    {
        this.mainMenu1 = new System.Windows.Forms.MainMenu();
        this.tabControl1 = new System.Windows.Forms.TabControl();
        this.SuspendLayout();
        // 
        // tabControl1
        // 
        this.tabControl1.Location = new System.Drawing.Point(0, 0);
        this.tabControl1.Name = "tabControl1";
        this.tabControl1.SelectedIndex = 0;
        this.tabControl1.Size = new System.Drawing.Size(240, 265);
        this.tabControl1.TabIndex = 0;
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
        this.AutoScroll = true;
        this.ClientSize = new System.Drawing.Size(240, 268);
        this.Controls.Add(this.tabControl1);
        this.Menu = this.mainMenu1;
        this.Name = "Form1";
        this.Text = "Form1";
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.TabControl tabControl1;
}

用户控件是UserControl1UserControl2

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    public void LoadComponent()
    {
        this.comboBox1.ValueMember = "Clave";
        this.comboBox1.DisplayMember = "Description";
        comboBox1.DataSource = getList();         
    }

    private List<Item> getList()
    {
        List<Item> list = new List<Item>();

        list.Add(new Item("0", "zero"));
        list.Add(new Item("1", "uno"));
        list.Add(new Item("2", "dos"));
        list.Add(new Item("3", "tres"));
        list.Add(new Item("4", "cuatro"));

        return new List<Item>(list);
    }

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        MessageBox.Show("Listo 1 ^^ SelectedIndexChanged ");    
    }
}

partial class UserControl1
{
    /// <summary> 
    /// Variable del diseñador requerida.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary> 
    /// Limpiar los recursos que se estén usando.
    /// </summary>
    /// <param name="disposing">true si los recursos administrados se deben eliminar; en caso contrario, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Código generado por el Diseñador de componentes

    /// <summary> 
    /// Método necesario para admitir el Diseñador. No se puede modificar 
    /// el contenido del método con el editor de código.
    /// </summary>
    private void InitializeComponent()
    {
        this.comboBox1 = new System.Windows.Forms.ComboBox();
        this.dataGrid1 = new System.Windows.Forms.DataGrid();
        this.SuspendLayout();
        // 
        // comboBox1
        // 
        this.comboBox1.Location = new System.Drawing.Point(24, 24);
        this.comboBox1.Name = "comboBox1";
        this.comboBox1.Size = new System.Drawing.Size(163, 22);
        this.comboBox1.TabIndex = 6;
        this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
        // 
        // dataGrid1
        // 
        this.dataGrid1.BackgroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(128)))), ((int)(((byte)(128)))));
        this.dataGrid1.Location = new System.Drawing.Point(24, 89);
        this.dataGrid1.Name = "dataGrid1";
        this.dataGrid1.Size = new System.Drawing.Size(163, 134);
        this.dataGrid1.TabIndex = 7;
        // 
        // UserControl1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
        this.Controls.Add(this.dataGrid1);
        this.Controls.Add(this.comboBox1);
        this.Name = "UserControl1";
        this.Size = new System.Drawing.Size(216, 266);
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.ComboBox comboBox1;
    private System.Windows.Forms.DataGrid dataGrid1;

}

public partial class UserControl2 : UserControl
{
    public UserControl2()
    {
        InitializeComponent();
    }

    public void LoadComponent()
    {
        this.comboBox2.ValueMember = "Clave";
        this.comboBox2.DisplayMember = "Description";
        this.comboBox2.DataSource = getList();
    }

    public List<Item> getList()
    {
        List<Item> list = new List<Item>();
        list.Add(new Item("0", "zero"));
        list.Add(new Item("1", "uno"));
        list.Add(new Item("2", "dos"));
        list.Add(new Item("3", "tres"));
        return new List<Item>(list);
    }

    private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
    {
        MessageBox.Show("Listo 2 ^^ SelectedIndexChanged ");      
    }
}

partial class UserControl2
{
    /// <summary> 
    /// Variable del diseñador requerida.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary> 
    /// Limpiar los recursos que se estén usando.
    /// </summary>
    /// <param name="disposing">true si los recursos administrados se deben eliminar; en caso contrario, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Código generado por el Diseñador de componentes

    /// <summary> 
    /// Método necesario para admitir el Diseñador. No se puede modificar 
    /// el contenido del método con el editor de código.
    /// </summary>
    private void InitializeComponent()
    {
        this.comboBox2 = new System.Windows.Forms.ComboBox();
        this.SuspendLayout();
        // 
        // comboBox2
        // 
        this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown;
        this.comboBox2.Location = new System.Drawing.Point(21, 27);
        this.comboBox2.Name = "comboBox2";
        this.comboBox2.Size = new System.Drawing.Size(163, 22);
        this.comboBox2.TabIndex = 0;
        this.comboBox2.SelectedIndexChanged += new System.EventHandler(this.comboBox2_SelectedIndexChanged);
        // 
        // UserControl2
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
        this.Controls.Add(this.comboBox2);
        this.Name = "UserControl2";
        this.Size = new System.Drawing.Size(216, 266);
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.ComboBox comboBox2;
}

这是真实代码的简化版本。为什么加载第二个用户控件的组合框数据源时会触发此事件?

call process pool 事件池进程的图像。

【问题讨论】:

  • 您可以在此处添加代码的事件订阅部分吗?
  • 我添加了设计器代码。谢谢

标签: c# windows-forms-designer windows-mobile-6.5


【解决方案1】:

尝试订阅SelectionChangeCommitted 事件

这样,当以编程方式进行更改时它不会触发,这是数据源加载的情况

【讨论】:

  • 此事件在 windows mobile 6.5 的 framework .net compact edition 中不存在。
  • 所以...我猜你必须在加载数据源之后而不是之前以编程方式订阅 SelectionChanged 事件
  • 我在设置第一个组合框(comboBoxB_SelectedIndexChanged)的第二个数据源触发事件后更改事件,这是同样的问题。 public void LoadComponent() { this.comboBoxA.ValueMember = "Clave"; this.comboBoxA.DisplayMember = "描述"; this.comboBoxA.DataSource = getList(); this.comboBoxA.SelectedIndexChanged += new System.EventHandler(this.comboBoxA_SelectedIndexChanged); }
  • 我已经对问题进行了测试,但我对问题的描述是错误的。此代码不会产生此错误,仅当其他组件在表单中时才会发生此错误。现在我编辑以暴露问题。
  • 3 因果关系 | 1 - usercontrol [combobox, datagrid ] 2- usercontrol[combobox] - 无检查 |||1 - usercontrol [combobox] 2- usercontrol[combobox] - 检查 |||1 - usercontrol [combobox, datagrid ] 2- usercontrol[combobox , datagrid ] - 检查
【解决方案2】:

首先是一些小的外观变化:

private List<Item> getList()
{
    ...
    return list;
}

而不是

public List<Item> getList()
{
    ...
    return new List<Item>(list);
}

然后移动事件处理器赋值:

    this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);

从设计器代码到 LoadComponent()

    public void LoadComponent()
    {
        this.comboBox1.ValueMember = "Clave";
        this.comboBox1.DisplayMember = "Description";
        comboBox1.DataSource = getList();
        this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
    }

可以通过从第一个加载的 UserControl 中删除 DataGrid 来解决此问题。例如,如果 DataGrid 在第二个加载的 UserControl 上,问题将不会显示:

    private void InitializeUserControl()
    {
        InitiliazeTab2();
        InitiliazeTab1();
    }

无法找到根本原因,即为什么在第一个 UserControl 中加载 DataGrid 时会触发 ComboBox SelectedIndexChanged 事件。对此没有合乎逻辑的记录说明,而且我不知道如何调试 Compact Framework 的事件冒泡。

为了方便其他人测试,这里有一个 VS2005 项目可以玩:https://github.com/hjgode/StackOverflow/tree/master/SmartDeviceProject1

【讨论】:

    【解决方案3】:

    我已解决在每个用户控件中合并一个数据网格。这个错误不合逻辑,应该是框架库错误。

    谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-01
      • 2013-01-01
      • 1970-01-01
      相关资源
      最近更新 更多