J'ai une application Windows .net 3.5 avec une liste déroulante liée. J'ai remplacé l'événement DrawItem pour colorer l'arrière-plan des éléments individuels en fonction de certaines conditions. J'ai des threads asynchrones qui mettent à jour les valeurs de condition et appellent Invalidate() pour redessiner la combobox.redessiner les éléments de la liste déroulante lors de l'expansion
Tout cela fonctionne très bien, sauf lorsque la liste déroulante est développée - DrawItem n'est appelé que pour l'élément mis en surbrillance dans la liste. Les autres éléments ne sont actualisés que lorsque l'utilisateur fait quelque chose, comme passer la souris sur un autre élément de la liste ou cliquer sur un autre contrôle. Je souhaite que les autres éléments soient automatiquement redessinés lorsque la liste est ouverte. Comment puis-je y arriver? C'est possible?
grâce
modifier: Je déterminé que tout élément est mis en évidence dans la liste élargie est redessinée dans l'affichage principal combobox. aucun élément de la liste n'est redessiné dans la partie développée du contrôle.
edit: voici un exemple simplifié. pour tous ceux qui veulent tester vous devriez être en mesure de créer une nouvelle application Windows Forms et l'ajouter dans un nouveau fichier de classe et il devrait construire. Pour reproduire le comportement, cliquez sur le bouton "détecter", puis ouvrez la liste déroulante et survolez COM1. les résultats des tests se termineront dans l'ordre de 1,3,2. vous pouvez voir que pendant que la liste déroulante est ouverte, COM3 reste jaune jusqu'à ce que vous déplaciez la surbrillance par-dessus, puis hors tension.
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; }
}
}