【问题标题】:Creating ImageList object in a loop在循环中创建 ImageList 对象
【发布时间】:2016-07-12 09:54:36
【问题描述】:

我对创建列表视图项有非常简单的逻辑。我将 dataGridView 中的所有 col 标题名称存储到 ColNamesForm1 数组中,然后仅比较最后 5 个字符是否与 (num)(cat)强>字符串。对于这两个选项,我使用存储在静态类 OtherFunctions 中的 Populate 函数将不同的图片附加到列表视图 lvMoveFrom 中。

但是我的代码有问题,因为在最后一次迭代之后,它从最后一列附加图像 - 如果第一列是 (num),最后一列是 (cat),则列表视图中的图像都是相同的 - 来自 cat图片。

我该如何解决这个问题?我想知道为每一列创建新的 ImageList 对象,但我不知道如何动态地做到这一点,例如使用循环索引 i。

请您帮忙解决我的问题。

private void Form1_Load(object sender, EventArgs e)
{
    for (int i = 0; i < ColNamesForm1.Length; i++)
    {
        if (ColNamesForm1[i].ToString().Substring(0, 4).ToUpper() != "COL_" && Regex.IsMatch(ColNamesForm1[i].ToString().Substring(4, 1), @"^\d+$") == false)
        {
            if (ColNamesForm1[i].ToString().Substring(ColNamesForm1[i].ToString().Length - 5) == "(num)")
            {
                OtherFunctions.Populate(lvMoveFrom, ColNamesForm1[i].ToString(), @"C:\pictures\num.png");
            }
            else
            {
                OtherFunctions.Populate(lvMoveFrom, ColNamesForm1[i].ToString(), @"C:\pictures\cat.png");
            }
        }
    }
}

public static void Populate(ListView lv, string itemName, string pathToPicture)
{
    ImageList img = new ImageList();
    img.ImageSize = new Size(30, 30);
    img.Images.Add(Image.FromFile(pathToPicture));
    lv.SmallImageList = img;
    lv.Items.Add(itemName, 0);
}

【问题讨论】:

  • ColNamesForm1[i].ToString().Substring(ColNamesForm1[i].ToString().Length - 5) == "(num)" 等于 ColNamesForm1[i].ToString().EndsWith("(num)")
  • ColNamesForm1是什么类型
  • 可以,因为每次调用lv.SmallImageList = img; 时都使用相同的ListView,所以最后一组图像将是lv 使用的图像。你应该给每个Item一张图片

标签: c# winforms


【解决方案1】:

问题

所以基本上是这样的:

ImageList img = new ImageList();
img.ImageSize = new Size(30, 30);
img.Images.Add(Image.FromFile(pathToPicture));
lv.SmallImageList = img;
lv.Items.Add(itemName, 0);

正在向ListView 添加新图像列表。您每次都通过相同的ListView(因此您实际上是在覆盖它)。其次,一行:

lv.Items.Add(itemName, 0);

第二个参数是图像列表中的索引(您分配给ListView)。所以给它0 将要求ListViewlv.SmallImageList[0](伪代码)中选择图像。

解决方案

为了消除覆盖,我将图像设置逻辑从Populate 中提取出来,并将其放回主方法中。我将分解设置逻辑:

ImageList img = new ImageList();
img.ImageSize = new Size(30, 30);

var paths = new List<string> { @"C:\pictures\num.png", @"C:\pictures\cat.png" };
paths.ForEach(path => img.Images.Add(MediaTypeNames.Image.FromFile(path)));

lvMoveFrom.SmallImageList = img;

我将所有图像路径放入List&lt;string&gt; 中,然后使用LINQ ForEach 迭代每个将其添加到ImageList img 的路径。与您的原始代码没有区别,除了我将所有图像添加到 ListView 并且我只执行一次

为了让你的代码更容易理解,我做了一些简单的重构。

首先是反转 if 语句:

if (ColNamesForm1[i].ToString().Substring(0, 4).ToUpper() != "COL_" && Regex.IsMatch(ColNamesForm1[i].ToString().Substring(4, 1), @"^\d+$") == false)

收件人:

if (ColNamesForm1[i].ToString().Substring(0, 4).ToUpper() == "COL_"
                || Regex.IsMatch(ColNamesForm1[i].ToString().Substring(4, 1), @"^\d+$"))
{
    continue;
}

这几乎就像一个保护子句,它说如果我们不满足这些最低条件,则移动到下一项。

然后我通过减少重复简化了您的方法执行:

if (ColNamesForm1[i].ToString().Substring(ColNamesForm1[i].ToString().Length - 5) == "(num)")
{
     OtherFunctions.Populate(lvMoveFrom, ColNamesForm1[i].ToString(), @"C:\pictures\num.png");
}
else
{
      OtherFunctions.Populate(lvMoveFrom, ColNamesForm1[i].ToString(), @"C:\pictures\cat.png");
}

收件人:

var image = ColNamesForm1[i].ToString().EndsWith("(num)")
                ? 0 // corresponds with the position of the image in the ImageList
                : 1;

OtherFunctions.Populate(lvMoveFrom, ColNamesForm1[i].ToString(), image);

最后你会看到我改变了你的Populate 方法。首先,我们使用图像预填充您的ListView,然后使用该三元运算符选择要显示的图像索引。

全部代码是:

private void Form1_Load(object sender, EventArgs e)
{
    ImageList img = new ImageList();
    img.ImageSize = new Size(30, 30);

    var paths = new List<string> { @"C:\pictures\num.png", @"C:\pictures\cat.png" };
    paths.ForEach(path => img.Images.Add(Image.FromFile(path)));

    lvMoveFrom.SmallImageList = img;

    for (int i = 0; i < ColNamesForm1.Length; i++)
    {
        if (ColNamesForm1[i].ToString().Substring(0, 4).ToUpper() == "COL_"
            || Regex.IsMatch(ColNamesForm1[i].ToString().Substring(4, 1), @"^\d+$"))
        {
            continue;
        }

        var image = ColNamesForm1[i].ToString().EndsWith("(num)")
                        ? 0 // corresponds with the position of the image in the ImageList
                        : 1;


        OtherFunctions.Populate(lvMoveFrom, ColNamesForm1[i].ToString(), image);
    }
}

public static void Populate(ListView lv, string itemName, int imageIndex)
{

    lv.Items.Add(itemName, imageIndex);
}

现在您可以进一步简化:

private void Form1_Load(object sender, EventArgs e)
{
    ImageList img = new ImageList();
    img.ImageSize = new Size(30, 30);

    var paths = new List<string> { @"C:\pictures\num.png", @"C:\pictures\cat.png" };
    paths.ForEach(path => img.Images.Add(Image.FromFile(path)));

    lvMoveFrom.SmallImageList = img;

    for (int i = 0; i < ColNamesForm1.Length; i++)
    {
        if (ColNamesForm1[i].ToString().Substring(0, 4).ToUpper() == "COL_"
            || Regex.IsMatch(ColNamesForm1[i].ToString().Substring(4, 1), @"^\d+$"))
        {
            continue;
        }

        var image = ColNamesForm1[i].ToString().EndsWith("(num)")
                        ? 0 // corresponds with the position of the image in the ImageList
                        : 1;

        lvMoveFrom.Items.Add(ColNamesForm1[i].ToString(), image);    
    }
}

【讨论】:

  • 非常感谢!我对部分路径有疑问。ForEach(path => img.Images.Add(MediaTypeNames.Image.FromFile(path))); “System.Net.Mime.MediaTypeNames.Image”不包含“FromFile”的定义我该如何处理?
  • 我只是用paths.ForEach(path => img.Images.Add(Image.FromFile(path)));
  • 非常感谢,您的解决方案真的很棒,感谢您的宝贵时间。
猜你喜欢
  • 2015-02-04
  • 2018-01-16
  • 2016-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多