自定义组合框:防止设计器添加到项目
Custom ComboBox: prevent designer from adding to Items
我有一个自定义组合框控件,它应该显示可用的网络摄像头列表。
代码相当小。
using System;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using DirectShowLib;
namespace CameraSelectionCB
{
public partial class CameraComboBox : ComboBox
{
protected BindingList<string> Names;
protected DsDevice[] Devices;
public CameraComboBox()
{
InitializeComponent();
Devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
Names = new BindingList<string>(Devices.Select(d => d.Name).ToList());
this.DataSource = Names;
this.DropDownStyle = ComboBoxStyle.DropDownList;
}
}
}
但是,我 运行 遇到了一些错误。
首先,每当我放置此组合框的实例时,设计器都会生成以下代码:
this.cameraComboBox1.DataSource = ((object)(resources.GetObject("cameraComboBox1.DataSource")));
this.cameraComboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cameraComboBox1.Items.AddRange(new object[] {
"HP Webcam"});
这会导致运行时出现异常,因为设置 DataSource 时不应修改 Items。即使我不触摸设计器中的项目 属性,也会发生这种情况。
"HP Webcam" 是当时我电脑上唯一的摄像头。
如何抑制这种行为?
问题是设计者 运行 构造函数中的绑定。您可以尝试将其移动到 Initialise 或 Loaded 事件
当您将控件放在窗体上时,构造函数代码和任何加载代码都将 运行。其中任何更改 属性 值的代码都将在设计时执行,因此将写入您放置控件的表单的 designer.cs 中。
在编程控制时,您应该始终牢记这一点。
我通过添加一个 属性 来解决这个问题,我可以用它来检查代码是在设计时还是在 运行 时执行的。
protected bool IsInDesignMode
{
get { return DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime; }
}
protected BindingList<string> Names;
protected DsDevice[] Devices;
public CameraComboBox()
{
InitializeComponent();
if (InDesignMode == false)
{
// only do this at runtime, never at designtime...
Devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
Names = new BindingList<string>(Devices.Select(d => d.Name).ToList());
this.DataSource = Names;
}
this.DropDownStyle = ComboBoxStyle.DropDownList;
}
现在绑定只会在运行时间
发生
尝试此操作时不要忘记删除 Designer.cs 文件中生成的代码
我有一个自定义组合框控件,它应该显示可用的网络摄像头列表。
代码相当小。
using System;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using DirectShowLib;
namespace CameraSelectionCB
{
public partial class CameraComboBox : ComboBox
{
protected BindingList<string> Names;
protected DsDevice[] Devices;
public CameraComboBox()
{
InitializeComponent();
Devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
Names = new BindingList<string>(Devices.Select(d => d.Name).ToList());
this.DataSource = Names;
this.DropDownStyle = ComboBoxStyle.DropDownList;
}
}
}
但是,我 运行 遇到了一些错误。 首先,每当我放置此组合框的实例时,设计器都会生成以下代码:
this.cameraComboBox1.DataSource = ((object)(resources.GetObject("cameraComboBox1.DataSource")));
this.cameraComboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cameraComboBox1.Items.AddRange(new object[] {
"HP Webcam"});
这会导致运行时出现异常,因为设置 DataSource 时不应修改 Items。即使我不触摸设计器中的项目 属性,也会发生这种情况。
"HP Webcam" 是当时我电脑上唯一的摄像头。
如何抑制这种行为?
问题是设计者 运行 构造函数中的绑定。您可以尝试将其移动到 Initialise 或 Loaded 事件
当您将控件放在窗体上时,构造函数代码和任何加载代码都将 运行。其中任何更改 属性 值的代码都将在设计时执行,因此将写入您放置控件的表单的 designer.cs 中。
在编程控制时,您应该始终牢记这一点。
我通过添加一个 属性 来解决这个问题,我可以用它来检查代码是在设计时还是在 运行 时执行的。
protected bool IsInDesignMode
{
get { return DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime; }
}
protected BindingList<string> Names;
protected DsDevice[] Devices;
public CameraComboBox()
{
InitializeComponent();
if (InDesignMode == false)
{
// only do this at runtime, never at designtime...
Devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
Names = new BindingList<string>(Devices.Select(d => d.Name).ToList());
this.DataSource = Names;
}
this.DropDownStyle = ComboBoxStyle.DropDownList;
}
现在绑定只会在运行时间
发生尝试此操作时不要忘记删除 Designer.cs 文件中生成的代码