在自定义控件中创建项集合

时间:2016-06-20 11:40:22

标签: winforms collections custom-controls

我在WinForm中有一个继承自Control类的Custom控件。我的控件包含多个面板和其他UIElements。

这就是我的控制应该是什么样子 enter image description here

有一个数据库面板, 数据库面板仅包含一个复选框。

并且有一个Server面板, 服务器面板包含许多数据库面板和单个标签;标题标签。

最后是容器面板,其中包含我的所有服务器面板。

我发现了这个Item Collection option for a User Control,但我无法理解接受的答案。如果有人能帮助解释它会更好。

另外,如果有人可以放一些链接来创建高级自定义控件。我整天都在读它,我仍然无法理解这一切。是否有高级自定义控件的分步指南?

[修改

基本上我需要的是在我的自定义控件中创建自定义集合。目前我的控件是构建为Winform控件库,我构建它然后我在我的主程序中使用。 所以在我的主程序中,我可以将组件拖放到我的表单上并使用它。

默认情况下,自定义控件将加载一个包含一个数据库的服务器。 我想要的是,如果我需要,可以在我的MAIN程序中添加/删除其他数据库/服务器

我很难解释我需要什么,因为我根本不明白整个自定义控件/项目收集的事情是如何工作的,我很抱歉。我真的很感激一些明确解释这些内容的链接

这是我控制的代码:

此代码仅创建我的默认控件,但我无法添加到它。集合属性出现在我的属性窗口中,但是当我向其添加项目并单击时,没有任何反应。

public class Database : System.Windows.Forms.Panel
{
    public CheckBox _ckbDatabase;

    public Database()
    {
        _ckbDatabase = new CheckBox();

        this.BackColor = _pnlDatabaseBackColor;
        this.Size = _pnlDatabaseSize;
        this.AutoSize = false;
        this.Height = 40;
        this.Width = 200;
        this.Location = _pnlDatabaseLocation;
        _ckbDatabase.Top = 10;
        _ckbDatabase.Left = 15;
        _ckbDatabase.TextAlign = _ckbdbTextAlignment;
        _ckbDatabase.Font = _ckbdbFont;
        _ckbDatabase.ForeColor = Color.White;

        this.Controls.Add(_ckbDatabase);

    }

    #Propterties
}

public class Server : System.Windows.Forms.Panel
{
    private Label _lblserver;
    private Database database;

    public Server()
    {
        _lblserver = new Label();
        database = new Database();
        this.BackColor = _pnlServerBackColor;
        this.Size = _pnlServerSize;
        this.AutoSize = false;
        _lblserver.Dock = _lblserverDock;
        _lblserver.Font = _lblsrvFont;
        _lblserver.BackColor = _lblServerBackColor;
        _lblserver.AutoSize = false;
        _lblserver.Text = SRV;

        database.Top = 35;
        database._ckbDatabase.Text = DB;

        this.Controls.Add(_lblserver);
        this.Controls.Add(database);
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public DatabaseCollection DatabaseCollection { get; set; }

    #Propterties
 }

public class ServersCollection : CollectionBase
{
    public Server this[int index]
    {
        get { return (Server)List[index]; }
    }
    public void Add(Server server)
    {
        List.Add(server);
    }
    public void Remove(Server server)
    {
        List.Remove(server);
    }
}

2 个答案:

答案 0 :(得分:0)

如此简单的事情:

public class Server {
    public string Name { get; set; }
    public List<Database> Databases { get; set; }

    public Server() {
        Databases = new List<Database>();
    }
}

public class Database {
    public string Name { get; set; }
    public bool Enabled { get; set; }
}

然后你可以像这样添加它:

        List<Server> servers = new List<Server>();

        Server serverA = new Server { Name = "Server A" };
        serverA.Databases.Add(new Database { Name = "Database 1", Enabled = true });
        serverA.Databases.Add(new Database { Name = "Database 2", Enabled = false });

        Server serverB = new Server { Name = "Server B" };
        serverB.Databases.Add(new Database { Name = "Database 1", Enabled = false });
        serverB.Databases.Add(new Database { Name = "Database 2", Enabled = false });

        servers.Add(serverA);
        servers.Add(serverB);

当您链接到项目集合部分时,您似乎希望能够在设计模式下添加服务器和数据库,但是您提到您希望通过代码执行此操作?如果这不是您想要的,您需要向我们提供更多信息。

答案 1 :(得分:0)

在我看来,你几乎就在那里。首先,这是一个更完整的集合类:

public class ServersCollection : IEnumerable<Server>
{
    private List<Server> _servers = new List<Server>();

    public Server this[int index]
    {
        get { return _servers[index]; }
    }

    public IEnumerator<Server> GetEnumerator()
    {
        foreach (var server in _servers)
            yield return server;
    }
    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }

    public void Add(Server server)
    {
        _servers.Add(server);
    }

    public void Remove(Server server)
    {
        //You might consider a deliberate loop to evaluate a proper match
        //Don't forget to Dispose() it first!
        _servers.Remove(server);
    }

    public void Clear()
    {
        for (Int32 i = _servers.Count - 1; i >= 0; i--)
            _servers[i].Dispose();
        _servers.Clear();
    }
}

ServersCollection类的实例添加到容器控件,顶层的实例容纳服务器面板:

private ServersCollection _servers = new ServersCollection();
public ServersCollection Servers { get { return _servers; } }

使用它作为一种方法,可以将Server控件添加到自己的控件集合中。

再次对DatabaseCollection类中的Server执行类似操作,以便它可以将Database面板添加到其控件集合中。

然后,只要你有一个控件实例,你也可以访问它所拥有的集合:

myControl.Servers
//-or-
myServer.Databases

...允许你添加/删除,如下:

myControl.Servers.Add(new Server());
//-or-
myServer.Databases.Add(new Database());

重点

您的类是控件,但它们也拥有其他控件。正确使用Dispose模式至关重要,否则您将始终遇到内存问题。

我会删除这些行,除非您打算在表单设计时添加服务器/ DB(即固定条目或默认值),否则它们无关紧要:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public DatabaseCollection DatabaseCollection { get; set; }

最后,您可以(应该!)进一步采用该集合类,Add()Remove()的重载可以更好地决定何时/如何/做什么不仅仅是基于例如,例如按名字?您还可以添加另一个索引器来提取名称,例如,而不仅仅是索引(您可能不太知道)。