扩展时重绘combobox项目

我有一个.net 3.5窗口应用程序绑定combobox。 我已经重写了DrawItem事件来根据特定的条件为单个项目的背景着色。 我有asynchronous线程运行更新条件值并调用Invalidate()获取combobox重绘。

这一切都很好,除了当combobox展开时 – 只有在列表中突出显示的项目才会调用DrawItem。 其他项目只有在用户执行某些操作时才会刷新,如将鼠标hover在列表中的其他项目上,或者单击其他控件。 我希望其他项目在打开列表时自动重画。 我如何做到这一点? 可能吗?

谢谢

编辑:我确定在扩展列表中突出显示的任何项目都在主combobox显示中重绘。 列表中没有项目在控件的扩展部分中重绘。

编辑:这是一个精简的示例表单。 对于任何想要testing的人来说,都应该能够创build一个新的Windows窗体应用程序,并将其添加到一个新的类文件中,然后构build它。

重现行为,单击“检测”button,然后打开combobox并hover在COM1上。 testing结果将以1,3,2的顺序完成。 您可以看到,当combobox打开时,COM3会保持黄色,直到您将亮点移到其上,然后closures。

using System; using System.Windows.Forms; using System.Collections.Generic; using System.IO.Ports; using System.Diagnostics; using System.Drawing; namespace combocolor { public partial class Demo2 : Form { private System.ComponentModel.IContainer components = null; private System.Windows.Forms.Label ComPortLabel; private System.Windows.Forms.ComboBox ComPortComboBox; private System.Windows.Forms.ErrorProvider MainErrorProvider; private System.Windows.Forms.Button autoQueryButton; delegate PortTestResult TestPortDelegate(string portName); delegate void UpdateTestResultsDelegate(PortTestResult portTestResult); string[] _ports = new string[] { "COM1", "COM2", "COM3" }; Dictionary<string, int> _autoDetectResults = null; public Demo2() { InitializeComponent(); } private void Settings_Load(object sender, EventArgs e) { this.ComPortComboBox.Items.AddRange(this._ports); this.ComPortComboBox.SelectedIndex = 0; } private void autoQueryButton_Click(object sender, EventArgs e) { // start port testing this._autoDetectResults = new Dictionary<string, int>(this._ports.Length); foreach (string portName in this._ports) { this._autoDetectResults.Add(portName, 0); this.ComPortComboBox.Invalidate(); try { TestPortDelegate testDel = new TestPortDelegate(TestSerialPort); // check port on a new thread testDel.BeginInvoke(portName, new AsyncCallback(TestFinishedCallback), testDel); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); } } } private void ComPortComboBox_DrawItem(object sender, DrawItemEventArgs e) { SolidBrush backgroundBrush, foregroundBrush; Dictionary<int, Color> colormap = new Dictionary<int, Color>(); colormap.Add(0, Color.Yellow); colormap.Add(-1, Color.Red); colormap.Add(1, Color.LimeGreen); string itemText = (string)ComPortComboBox.Items[e.Index]; // select a background color based on autodetect status if (this._autoDetectResults == null) { backgroundBrush = new System.Drawing.SolidBrush(e.BackColor); } else { int key = this._autoDetectResults[itemText]; backgroundBrush = new SolidBrush(colormap[key]); } if ((e.State & DrawItemState.Selected) > 0 && (e.State & DrawItemState.ComboBoxEdit) == 0) { e.DrawBackground(); // draws the blue highlight foregroundBrush = new SolidBrush(e.ForeColor); // text color } else { e.Graphics.FillRectangle(backgroundBrush, e.Bounds); // draws the color based on the autodetect results foregroundBrush = new SolidBrush(this.ComPortComboBox.ForeColor); // text color } e.Graphics.DrawString(itemText, e.Font, foregroundBrush, e.Bounds); // draw the text } private PortTestResult TestSerialPort(string portName) { PortTestResult result = new PortTestResult(); result.PortName = portName; // simulated results switch (portName) { case "COM1": System.Threading.Thread.Sleep(2000); result.UseThisPort = false; break; case "COM2": System.Threading.Thread.Sleep(6000); result.UseThisPort = true; break; case "COM3": System.Threading.Thread.Sleep(4000); result.UseThisPort = false; break; } return result; } private void TestFinishedCallback(IAsyncResult ar) { // get the results from the test function TestPortDelegate testPortDelegate = (TestPortDelegate)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate; PortTestResult portTestResult = testPortDelegate.EndInvoke(ar); UpdateTestResults(portTestResult); // pass the results along to update the UI } private void UpdateTestResults(PortTestResult portTestResult) { if (this.ComPortComboBox.InvokeRequired) { UpdateTestResultsDelegate updateTestResultsDelegate = new UpdateTestResultsDelegate(UpdateTestResults); this.Invoke(updateTestResultsDelegate, portTestResult); } else { // set status based on test result if (portTestResult.UseThisPort) { this._autoDetectResults[portTestResult.PortName] = 1; // 1 for a good response this.ComPortComboBox.SelectedItem = portTestResult.PortName; } else { this._autoDetectResults[portTestResult.PortName] = -1; // -1 for a bad response } this.ComPortComboBox.Invalidate(); // force the combobox to redraw with new colors } } protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.ComPortComboBox = new System.Windows.Forms.ComboBox(); this.ComPortLabel = new System.Windows.Forms.Label(); this.MainErrorProvider = new System.Windows.Forms.ErrorProvider(this.components); this.autoQueryButton = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.MainErrorProvider)).BeginInit(); this.SuspendLayout(); this.ComPortComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; this.ComPortComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.ComPortComboBox.FormattingEnabled = true; this.ComPortComboBox.Location = new System.Drawing.Point(71, 12); this.ComPortComboBox.Name = "ComPortComboBox"; this.ComPortComboBox.Size = new System.Drawing.Size(136, 21); this.ComPortComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComPortComboBox_DrawItem); this.ComPortLabel.Location = new System.Drawing.Point(12, 15); this.ComPortLabel.Name = "ComPortLabel"; this.ComPortLabel.Size = new System.Drawing.Size(53, 13); this.ComPortLabel.Text = "&Com Port:"; this.autoQueryButton.Location = new System.Drawing.Point(213, 11); this.autoQueryButton.Name = "autoQueryButton"; this.autoQueryButton.Size = new System.Drawing.Size(49, 21); this.autoQueryButton.Text = "detect"; this.autoQueryButton.UseVisualStyleBackColor = false; this.autoQueryButton.Click += new System.EventHandler(this.autoQueryButton_Click); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(282, 47); this.Controls.Add(this.autoQueryButton); this.Controls.Add(this.ComPortLabel); this.Controls.Add(this.ComPortComboBox); this.Name = "Demo"; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Load += new System.EventHandler(this.Settings_Load); ((System.ComponentModel.ISupportInitialize)(this.MainErrorProvider)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } } public class PortTestResult { public string PortName { get; set; } public bool UseThisPort { get; set; } } } 

这个CodeProject文章有关于定制组合框的很好的信息: 文章