WinConms comboBox_SelectedValueChanged在tabControl_SelectedIndexChanged上触发三次 [英] WinForms comboBox_SelectedValueChanged fired thrice on tabControl_SelectedIndexChanged
问题描述
我有一个带有多个标签的tabcontrol元素。在选项卡2(索引1)上,我有一个管理模板选择的组合框。模板对象本身包含ID和名称
内部类模板
{
public Template(double id,string name)
{
ID = id;
姓名=姓名;
}
公共双重身份证{get;私人集; }
public string Name {get;私人集; }
}
$
使用这个组合框,我想显示名称并选择ID。我将提供一个完整的工作示例。
我的表格
public partial class Form1:Form
{
public Form1()
{
InitializeComponent();
cmbx = new Cmbx(comboBox1); //传入组合框元素
}
私人Cmbx cmbx; //我的组合框类
private void tabControl1_SelectedIndexChanged(object sender,EventArgs e)
{
if(tabControl1.SelectedIndex == 1)// tab 2是否有效?
{
cmbx.CreateTemplateSelection(myTemplates); // init组合框与模板列表
}
}
private void comboBox1_SelectedValueChanged(object sender,EventArgs e)
{
//处理新的这里选择的ID
MessageBox.Show($" Combobox Change Event - Selected ID {cmbx.SelectedTemplateID}");
}
}
$
和我的组合框类< br $>
class Cmbx
{
public Cmbx(ComboBox cmbx)
{
this .cmbx = cmbx;
}
私人ComboBox cmbx; // GUI元素
private Template [] currentTemplates;
public double SelectedTemplateID //获取当前选定的值
{
get
{
Template templateInfo = cmbx.SelectedValue as Template;
返回templateInfo.ID;
}
}
public void CreateTemplateSelection(Template [] templates)//填充组合框
{
if(currentTemplates!= null)//第一次?
{
if(currentTemplates.SequenceEqual(templates))//不同的数据?
{
return; //没有改变 - >返回
}
}
//不同数据
cmbx.DataSource = null; //清除组合框
cmbx.Items.Clear();
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = templates;
cmbx.DataSource = bindingSource.DataSource; //设置数据
cmbx.DisplayMember = nameof(Template.Name); //显示模板名称
cmbx.ValueMember = nameof(Template.ID); //选择模板ID
bool valid = templates.Length> 0; //现有数据?
if(valid&& cmbx.SelectedIndex!= 0)
cmbx.SelectedIndex = 0; //选择第一项
currentTemplates = templates; //将新模板分配给当前的模板
}
}
当运行项目并选择第二个选项卡时,`comboBox1_SelectedValueChanged`将触发3次。
在第一次和第二次运行时`cmbx.SelectedTemplateID`返回我选择的模板ID 1.这是正确的。
第三次运行会返回一个空指针。
为什么会发射3次?为什么第三个事件调用返回一个空指针?
>>为什么会激发3次?
"SelectedValueChanged""设置其DataSource,DisplayMember或ValueMember时将触发combox事件。
cmbx.DataSource = bindingSource.DataSource; //设置数据
cmbx.DisplayMember = nameof(Template.Name); //显示模板名称
cmbx.ValueMember = nameof(Template.ID); //选择模板ID因此,当执行上面的代码时,"comboBox1_SelectedValueChanged"将被触发。
>>为什么第三个事件调用返回一个空指针?
通过在get访问器的前面设置一个断点方法"SelectedTemplateID",你可以看到当"comboBox1_SelectedValueChanged"时第三次执行"cmbx.SelectedValue"。获取单个值而不是类型为"模板"的对象的
。因此无法将其转换为模板类型会导致错误。
为了解决此问题,您可以参考以下步骤。
I have a tabcontrol element with multiple tabs. On tab 2 (index 1) I have a combobox that manages a template selection. The template object itself holds an ID and a name
internal class Template { public Template(double id, string name) { ID = id; Name = name; } public double ID { get; private set; } public string Name { get; private set; } }
With this combobox I want to display the name and select the ID. I will provide a full working example.
My form
public partial class Form1 : Form { public Form1() { InitializeComponent(); cmbx = new Cmbx(comboBox1); // pass in the combobox element } private Cmbx cmbx; // My combobox class private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) { if (tabControl1.SelectedIndex == 1) // tab 2 active? { cmbx.CreateTemplateSelection(myTemplates); // init combobox with the templates list } } private void comboBox1_SelectedValueChanged(object sender, EventArgs e) { // handle the new selected ID here MessageBox.Show($"Combobox Change Event - Selected ID {cmbx.SelectedTemplateID}"); } }
and my combobox class
class Cmbx { public Cmbx(ComboBox cmbx) { this.cmbx = cmbx; } private ComboBox cmbx; // GUI element private Template[] currentTemplates; public double SelectedTemplateID // Get the current selected value { get { Template templateInfo = cmbx.SelectedValue as Template; return templateInfo.ID; } } public void CreateTemplateSelection(Template[] templates) // populate the combobox { if (currentTemplates != null) // first time? { if (currentTemplates.SequenceEqual(templates)) // different data? { return; // nothing changed -> return } } // different data cmbx.DataSource = null; // clear the combobox cmbx.Items.Clear(); BindingSource bindingSource = new BindingSource(); bindingSource.DataSource = templates; cmbx.DataSource = bindingSource.DataSource; // setup the data cmbx.DisplayMember = nameof(Template.Name); // display the template name cmbx.ValueMember = nameof(Template.ID); // select the template id bool valid = templates.Length > 0; // existing data? if (valid && cmbx.SelectedIndex != 0) cmbx.SelectedIndex = 0; // select the first item currentTemplates = templates; // assign the new templates to the current ones } }
When running the project and selecting the second tab the `comboBox1_SelectedValueChanged` fires 3 times.
On the first and second run `cmbx.SelectedTemplateID` returns me the selected template ID 1. This is correct.
The third run returns me a null pointer.
Why does it fire 3 times? And why does the third event call return a null pointer?解决方案Hi,
>> Why does it fire 3 times?
The "SelectedValueChanged" event of combox will be triggered when setting its DataSource, DisplayMember or ValueMember.
cmbx.DataSource = bindingSource.DataSource; // setup the data cmbx.DisplayMember = nameof(Template.Name); // display the template name cmbx.ValueMember = nameof(Template.ID); // select the template idSo when executing the above code, the "comboBox1_SelectedValueChanged" will be triggered.
>> And why does the third event call return a null pointer?
By setting a breakpoint in the front of the get accessor of method "SelectedTemplateID", you can see that when "comboBox1_SelectedValueChanged" is executed for the third time, "cmbx.SelectedValue" gets a single value instead of an object of type "Template". So the inability to convert it to a Template type caused an error.
In order to solve this problem, you can refer to the following steps.
这篇关于WinConms comboBox_SelectedValueChanged在tabControl_SelectedIndexChanged上触发三次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文