C# 如何添加具有特定文本颜色的列表框项目?
我试图从文本文件中将计算机列表添加到列表框中,并根据ping是否在计算机上成功,将其颜色设置为绿色表示成功,红色表示失败。问题是,它在所有项目上使用最后一台计算机的最后一种颜色。我相信这是因为Drawitem事件直到for循环完成后才被引发,但我想不出一种解决方法。感谢您的帮助。ping的简化代码C# 如何添加具有特定文本颜色的列表框项目?,c#,wpf,listbox,C#,Wpf,Listbox,我试图从文本文件中将计算机列表添加到列表框中,并根据ping是否在计算机上成功,将其颜色设置为绿色表示成功,红色表示失败。问题是,它在所有项目上使用最后一台计算机的最后一种颜色。我相信这是因为Drawitem事件直到for循环完成后才被引发,但我想不出一种解决方法。感谢您的帮助。ping的简化代码 private logitem linez; struct logitem { public string text; public Brus
private logitem linez;
struct logitem
{
public string text;
public Brush color;
};
private void browsebutton_Click(object sender, EventArgs e)
{
string textfile = ofd.FileName;
if (textfile != "")
{
string[] lines = System.IO.File.ReadAllLines(@textfile);
foreach (string line in lines)
{
if (line != "")
{
string liner;
liner = line.Replace(" ", "");
if (ping successfull)
{
listBoxAddGreen();
}
else (ping fails)
{
listBoxAddRed();
}
}
changeCount();
}
}
public void listBoxAddGreen ()
{
linez.color = Brushes.Green;
listBox1.Items.Add(linez.text);
}
public void listBoxAddRed ()
{
linez.color = Brushes.Red;
listBox1.Items.Add(linez.text);
}
private void listBox1_DrawItem(object sender,
System.Windows.Forms.DrawItemEventArgs e)
{
e.DrawBackground();
Brush myBrush = linez.color;
e.Graphics.DrawString(listBox1.Items[e.Index].ToString(),
e.Font, myBrush, e.Bounds, StringFormat.GenericDefault);
e.DrawFocusRectangle();
}
如果你愿意使用ListView控件,那就很容易了。首先,将视图设置为列表:
然后,您可以创建一个通用函数,将彩色项添加到ListView中。基本上,所有这一切都是先添加项目,然后使用它的索引(这将是最后一个),或计数-1来更改前景色:
private static void AddColoredItemToListView(ListView listView, string item, Color color)
{
listView.Items.Add(item);
listView.Items[listView.Items.Count - 1].ForeColor = color;
}
因为您没有包含Ping方法,所以我将在这里包含一个简单的方法:
public static bool PingServer(string serverName)
{
try { return new Ping().Send(serverName)?.Status == IPStatus.Success; }
catch { return false; }
}
现在,要调用该方法,我们只需读取服务器文件,并ping每个服务器。如果对PingServer的调用返回true,我们将颜色变量设置为绿色,否则将其设置为红色,然后调用上面创建的方法:
private void browsebutton_Click(object sender, EventArgs e)
{
var serversFile = @"f:\public\temp\servers.txt";
var servers = File.ReadAllLines(serversFile)
.Where(l => !string.IsNullOrWhiteSpace(l))
.Select(l => l.Replace(" ", ""));
foreach (var server in servers)
{
var color = PingServer(server)
? Color.Green
: Color.Red;
AddColoredItemToListView(listView1, server, color);
}
}
样本输出
或者,如果愿意,您可以更改背景色:
我对它进行了一些研究,发现我们可以用列表框做同样的事情。诀窍是添加一个同时存储颜色和文本的项。你是用一个结构做的,我用的是一个类:
class ColoredItem
{
public string Text;
public Color Color;
};
现在,我们可以用与我的另一个答案大致相同的方式创建彩色项目,其中我们ping服务器,如果ping成功,则将颜色设置为绿色,否则将其设置为红色。我们将Text属性设置为服务器名称。请注意,我们现在直接调用listBox1.Additem,因为我们依赖自定义绘制方法来更改颜色:
public static bool PingServer(string serverName)
{
try { return new Ping().Send(serverName)?.Status == IPStatus.Success; }
catch { return false; }
}
private void browsebutton_Click(object sender, EventArgs e)
{
var serversFile = @"f:\public\temp\servers.txt";
var servers = File.ReadAllLines(serversFile)
.Where(l => !string.IsNullOrWhiteSpace(l))
.Select(l => l.Replace(" ", ""));
foreach (var server in servers)
{
var color = PingServer(server)
? Color.Green
: Color.Red;
ColoredItem coloredItem = new ColoredItem {Color = color, Text = server};
listBox.Items.Add(coloredItem);
}
}
现在,在DrawItem方法中,我们尝试将该项强制转换为ColoredItem类的实例。请注意,DrawItemEventArgs包含我们正在添加的项的索引。调用DrawString方法时,现在可以使用item.Text作为服务器名称,item.Color作为笔刷颜色:
private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
var item = listBox1.Items[e.Index] as ColoredItem;
if (item != null)
{
e.Graphics.DrawString(
item.Text,
e.Font,
new SolidBrush(item.Color),
e.Bounds);
}
}
我们需要确保的另一件事是将ListBox的DrawMode设置为OwnerDrawFixed,以便调用我们的自定义绘图代码:
private void Form1_Load(object sender, EventArgs e)
{
listBox1.DrawMode = DrawMode.OwnerDrawFixed;
}
样本输出
您是否愿意使用ListView?更改颜色更容易操作。是否已将绘图模式设置为OwnerDrawnFixed?您必须熟悉MVVM。使用它,您的任务将在几分钟内得到解决。1在视图模型中执行ping;2每个ping项目都应该有自己的视图模型,例如,带有PingOk属性的ItemVM,显示ping是否成功;3将列表框的ItemsSource绑定到ItemVM集合;4在XAML中为ListBoxItem设置触发器,根据PingOk属性的值更改前景。ListBox比ListView对您的任务更有用,所以请坚持使用此items控件。效果很好,我认为主要问题在于我的DrawItem方法,该方法通过强制转换到ColoredItem类来修复。而且,您编写代码的方式更简单、更雄辩。我现在唯一要弄清楚的是如何让结果更快地显示出来。在绘制之前,它会等待所有项目都被ping'd
private void Form1_Load(object sender, EventArgs e)
{
listBox1.DrawMode = DrawMode.OwnerDrawFixed;
}