正在删除不正确的图片

时间:2010-11-30 13:15:37

标签: c# winforms user-controls

单击“删除所选项”按钮时,将删除错误的图片。大多数时候它删除了所选图片右侧的图片。其他时候,例如当选择了所有内容时,它只删除一张图片。

我不知道发生了什么事。这是一张图片来说明会发生什么:

alt text

以下是我正在使用的两个用户控件的代码:Horizo​​ntalPictureScroller和SelectablePicture。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using System.ComponentModel.Design.Serialization;

namespace WinformsPlayground
{    
    public partial class HorizontalPictureScroller : UserControl
    {
        public HorizontalPictureScroller()
        {
            InitializeComponent();
            Pictures = new ObservableCollection<SelectablePicture>();
            Pictures.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Pictures_CollectionChanged);
        }       

        #region "Properties"
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public ObservableCollection<SelectablePicture> Pictures { get; set; }
        private int PositionControlX = 0;
        #endregion

        #region "Methods"
        private void RedrawPictures()
        {
            PositionControlX = 0;

            foreach (var picture in Pictures)
            {
                picture.Location = new Point(PositionControlX + panelPicturesWrapper.AutoScrollPosition.X, 0);
                PositionControlX += 130;
                panelPicturesWrapper.Controls.Add(picture);
            }
        }

        public void AddPicture(SelectablePicture picture)
        {
            Pictures.Add(picture);
        }

        public void RemovePicture(SelectablePicture picture)
        {
            Pictures.Remove(picture);
        }

        public void MovePictureLeft(int index)
        {
            SelectablePicture tmpPicture = Pictures[index];
            Pictures[index] = Pictures[index - 1];
            Pictures[index - 1] = tmpPicture;
        }

        public void MovePictureRight(int index)
        {
            SelectablePicture tmpPicture = Pictures[index];
            Pictures[index] = Pictures[index + 1];
            Pictures[index + 1] = tmpPicture;
        }

        public void SelectAllImages()
        {
            foreach (var picture in panelPicturesWrapper.Controls)
            {
                ((SelectablePicture)picture).SelectPicture();
            }
        }

        public void DeselectAllImages()
        {
            foreach (var picture in panelPicturesWrapper.Controls)
            {
                ((SelectablePicture)picture).DeselectPicture();
            }
        }

        public void DeleteSelectedImages()
        {
            foreach (var picture in panelPicturesWrapper.Controls)
            {
                if (((SelectablePicture)picture).IsSelected())
                {
                    this.RemovePicture((SelectablePicture)picture);
                }
            }
        }
        #endregion

        #region "Events"
        void Pictures_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            RedrawPictures();
        }
        #endregion

    }
}



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Serialization;

namespace WinformsPlayground
{
    public partial class SelectablePicture : UserControl
    {
        public SelectablePicture()
        {
            InitializeComponent();
            panel1.BackgroundImageLayout = ImageLayout.Zoom;
        }

        public SelectablePicture(Image image)
        {
            InitializeComponent();
            panel1.BackgroundImage = image;
            panel1.BackgroundImageLayout = ImageLayout.Zoom;
        }

        #region "Properties"
        public Image Image()
        {
            return panel1.BackgroundImage;
        }

        public bool IsSelected()
        {
            return chkSelected.Checked;
        }
        #endregion

        #region "Methods"
        public void ToggleCheckBox()
        {
            chkSelected.Checked = chkSelected.Checked ? false : true;
        }

        public void VisuallySelect()
        {
            this.BackColor = Color.FromArgb(51, 153, 255);
        }

        public void VisuallyDeselect()
        {
            //If none of the controls inside the usercontrol have focus, set this control to white.
            if (!this.Focused && !this.panel1.Focused && !this.chkSelected.Focused)
            {
                this.BackColor = Color.White;
            }
        }        

        public void SelectPicture()
        {
            this.chkSelected.Checked = true;
        }

        public void DeselectPicture()
        {
            this.chkSelected.Checked = false;
        }
        #endregion

        #region "Events"
        private void panel1_Click(object sender, EventArgs e)
        {
            VisuallySelect();
            ToggleCheckBox();
            panel1.Focus();
        }

        private void chkSelected_Click(object sender, EventArgs e)
        {
            VisuallySelect();
            ToggleCheckBox();
            chkSelected.Focus();
        }

        private void SelectablePicture_Click(object sender, EventArgs e)
        {
            VisuallySelect();
            ToggleCheckBox();
            this.Focus();
        }

        private void panel1_Leave(object sender, EventArgs e)
        {
            VisuallyDeselect();
        }

        private void chkSelected_Leave(object sender, EventArgs e)
        {
            VisuallyDeselect();
        }

        private void SelectablePicture_Leave(object sender, EventArgs e)
        {
            VisuallyDeselect();
        }
        #endregion        
    }
}

代码很简单。我使用了断点,我可以确认Horizo​​ntalPictureScroller.DeleteSelectedImages()方法是否正确迭代选定的图片。我不知道我还能做些什么来看看发生了什么。我很难过!

有什么想法吗?也许Obse​​rvableCollection类型附带的.Remove()方法不能像我想象的那样工作。

1 个答案:

答案 0 :(得分:2)

每次图片集合更改时,您都在调用RedrawPictures。这会再次添加所有图片,但不会清除任何内容......因此,当它已包含该控件时,您将尝试向panelPicturesWrapper.Controls添加控件。这对我来说听起来不错。

此外,您在更改时会迭代Controls集合,这通常是一个坏主意。

我建议您将删除代码更改为以下内容:

public void DeleteSelectedImages()
{
    var picturesToRemove = panelPicturesWrapper.Controls
                                               .Cast<SelectablePicture>();
                                               .Where(p => p.IsSelected())
                                               .ToList();

    foreach (var picture in picturesToRemove)
    {
        RemovePicture(picture);
    }
}