每次构建后更改自定义 ListView.Items

Change the customized ListView.Items after each build

我创建了一个自定义的 ListView,它继承自 .NET 中的标准 ListView,以将 enum 值显示为其 Items(WinForms 项目):

public class ScrapGroupsListView : ListView
{
    public event EventHandler SelectedColorChanged;

    private ScrapGroup _selectedGroup = ScrapGroup.None;

    [DefaultValue(ScrapGroup.None)]
    public ScrapGroup SelectedScrapGroup
    {
        get { return _selectedGroup; }
        set
        {
            if (_selectedGroup != value)
            {
                _selectedGroup = value;
                foreach (ListViewItem item in this.Items)
                {
                    if (item != null)
                    {
                        if (item.Tag != null)
                        {
                            var itemColor = (ScrapGroup)item.Tag;
                            if (itemColor == ScrapGroup.None) 
                                item.Checked = value == ScrapGroup.None;
                            else
                                item.Checked = value.HasFlag(itemColor);
                        }
                    }
                }

                if (SelectedColorChanged != null) 
                   SelectedColorChanged.Invoke(this, EventArgs.Empty);
            }
        }
    }

    public ScrapGroupsListView()
    {
        this.Items.Clear();
        this.CheckBoxes = true;
        this.HeaderStyle = ColumnHeaderStyle.None;
        this.View = View.List;

        foreach (var value in Enum.GetValues(typeof(ScrapGroup)).Cast<ScrapGroup>())
        {
            this.Items.Add(new ListViewItem()
            {
                Name = value.ToString(),
                Text = value.ToString(),
                Tag = value,
            });
        }
    }

    protected override void OnItemChecked(ItemCheckedEventArgs e)
    {
        base.OnItemChecked(e);

        var checkedScrapGroup = (ScrapGroup)e.Item.Tag;

        if (e.Item.Checked)
            if (checkedScrapGroup == ScrapGroup.None)
                SelectedScrapGroup = ScrapGroup.None;
            else
                SelectedScrapGroup |= checkedScrapGroup;
        else
            SelectedScrapGroup &= ~checkedScrapGroup;
    }
}

ScrapGrouop 是我的枚举:

[Flags]
public enum ScrapGroup
{
    None=0,
    M=1,
    E=2,
    N=4,
    H=8
}

当我将 ScrapGroupsListView 放入我的表单时,一切正常并且控件没有项目:

但每次我构建项目时,ScrapGroup 值都会添加到 ScrapGroupsListView.Items(设计时):

第一次构建后:

第二次构建后:

等等。

问题出在哪里?

而不是构造函数尝试:

protected override void OnCreateControl()
    {
        base.OnCreateControl();

        this.Items.Clear();
        this.CheckBoxes = true;
        this.HeaderStyle = ColumnHeaderStyle.None;
        this.View = View.List;

        foreach (var value in Enum.GetValues(typeof(ScrapGroup)).Cast<ScrapGroup>())
        {
            this.Items.Add(new ListViewItem()
            {
                Name = value.ToString(),
                Text = value.ToString(),
                Tag = value,
            });
        }
    }

每次在 VS 设计器中打开表单时,它都会创建以下代码:

private void InitializeComponent()
{
    System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("None");
    System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem("M");
    System.Windows.Forms.ListViewItem listViewItem3 = new System.Windows.Forms.ListViewItem("E");
    System.Windows.Forms.ListViewItem listViewItem4 = new System.Windows.Forms.ListViewItem("N");
    System.Windows.Forms.ListViewItem listViewItem5 = new System.Windows.Forms.ListViewItem("H");
    this.scrapGroupsListView1 = new ScrapGroupsListView();
    // 
    // scrapGroupsListView1
    // 
    this.scrapGroupsListView1.CheckBoxes = true;
    this.scrapGroupsListView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
    listViewItem1.StateImageIndex = 0;
    listViewItem1.Tag = ScrapGroup.None;
    listViewItem2.StateImageIndex = 0;
    listViewItem2.Tag = ScrapGroup.M;
    listViewItem3.StateImageIndex = 0;
    listViewItem3.Tag = ScrapGroup.E;
    listViewItem4.StateImageIndex = 0;
    listViewItem4.Tag = ScrapGroup.N;
    listViewItem5.StateImageIndex = 0;
    listViewItem5.Tag = ScrapGroup.H;
    this.scrapGroupsListView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
    listViewItem1,
    listViewItem2,
    listViewItem3,
    listViewItem4,
    listViewItem5});

这就是您的项目出现两次的原因。第一组来自构造函数,第二组来自 InitializeComponent().

您可以(并且应该)从 InitializeComponent() 中删除代码,但在设计器中打开表单会再次搞砸。

为防止出现这种情况,您可以将填充代码移至单独的方法并从表单中调用它。

在你的控制之下:

public ScrapGroupsListView()
{
    this.CheckBoxes = true;
    this.HeaderStyle = ColumnHeaderStyle.None;
    this.View = View.List;
}

public void Fill()
{
    this.Items.Clear();

    foreach( var value in Enum.GetValues( typeof( ScrapGroup ) ).Cast<ScrapGroup>() )
    {
        this.Items.Add( new ListViewItem()
        {
            Name = value.ToString(),
            Text = value.ToString(),
            Tag = value,
        } );
    }
}

在您的表单中:

public MainForm()
{
    InitializeComponent();

    scrapGroupsListView1.Fill();
}

作为此解决方案的缺点,您无法在设计器中看到您的项目。