保持主要形式整洁 - 惯例

时间:2016-08-19 08:29:07

标签: c# forms winforms main hamburger-menu

这不是关于编码本身的问题,而是关于代码结构中的良好实践。我目前正在构建一个WinForms应用程序,几个小时之后,我的主表单包含130行代码。这可能不是很多,但这只包括事件处理 - 因为我试图通过为基本上所有内容提供单独的类文件来避免这种情况......但是现在所有的控件和事件都让我的主代码很难阅读。 / p>

现在这是一个我可以轻易找到的主题,我对如何解决这个问题有一些想法,比如创建自定义控件并将表单拆分成大部分。这有什么最好的做法吗?当80%的用户交互发生在这里时,如何保持主表单清洁?还有关于如何构建您可以推荐的项目(而不是代码)的基本指南吗?

(希望这是一个有效的问题)

谢谢!

编辑:我决定添加代码。看到任何冗余?

public partial class MainForm : Form
{
    string currentFilter = "all";

    public MainForm()
    {
        InitializeComponent();
    }
    private void MainForm_Load(object sender, System.EventArgs e)
    {
        RefreshGenres();
        RefreshMovies(currentFilter);
    }

    private void addToolStripMenuItem_Click(object sender, System.EventArgs e)
    {
        var fAdd = new AddNewForm();

        fAdd.SetDesktopLocation(MousePosition.X, MousePosition.Y);
        fAdd.ShowDialog();
    }

    private void refreshToolStripMenuItem_Click(object sender, System.EventArgs e)
    {
        RefreshGenres();
        RefreshMovies(currentFilter);
    }

    private void addCategoryToolStripMenuItem_Click(object sender, System.EventArgs e)
    {
        tvCategories.Nodes.Add(new TreeNode("category"));
        tvCategories.Nodes[tvCategories.Nodes.Count - 1].BeginEdit();
    }
    private void tvCategories_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
    {
        var genre = e.Label;
        var writer = new Writer();
        writer.AddGenre(e.Label);

    }


    private void everythingToolStripMenuItem_Click(object sender, System.EventArgs e)
    {
        EraseData("all");
    }
    private void clearGenres_Click(object sender, System.EventArgs e)
    {
        EraseData("genres");
    }
    private void clearMovies_Click(object sender, System.EventArgs e)
    {
        EraseData("movies");
    }
    private void EraseData(string eraseThis)
    {
        DialogResult r = MessageBox.Show("Are you sure?\nLost data can NOT be retrieved.", "Clear Data", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);

        var cmdText = "";

        if (r == DialogResult.Yes)
        {
            switch (eraseThis)
            {
                case "all":
                    cmdText = "TRUNCATE TABLE MOVIES GENRES";
                    break;

                case "movies":
                    cmdText = "TRUNCATE TABLE MOVIES";
                    break;

                case "genres":
                    cmdText = "TRUNCATE TABLE GENRES";
                    break;
            }
            conn.Open();
            using (var cmd = conn.CreateCommand())
            {
                cmd.CommandText = cmdText;
                cmd.ExecuteNonQuery();
            }
            conn.Close();
        }
    }


    private void RefreshGenres()
    {
        tvCategories.Nodes.Clear();

        var reader = new Reader();
        var genres = reader.GetGenreList();

        foreach (string str in genres)
        {
            tvCategories.Nodes.Add(str);
        }
    }
    private void RefreshMovies(string filter)
    {
        lvMovies.Items.Clear();

        var reader = new Reader();
        var movies = reader.GetMovieList(filter);

        foreach (ListViewItem item in movies)
        {
            lvMovies.Items.Add(item);
        }
        reader.conn.Close();

    }

    private void tvCategories_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        currentFilter = e.Node.Text;
        RefreshMovies(currentFilter);
    }
}

1 个答案:

答案 0 :(得分:1)

我认为这里的问题不是你的代码的长度,而是你混合了很多不同的东西而你并没有以一致的方式处理你的事件。 这些是我要改变的主要内容:

EraseData:此方法打开并使用数据库连接,这是您通常应该避免的(更改数据库中的某些内容会导致您修改UI代码),您的WinForm代码不应该知道数据的位置暴露来自。在这里,您最好在Writer类中添加EraseData。

RefreshMovies:它与RefreshGenres完全不同,即使这两种方法基本上都做同样的事情:它们正在获取添加到某些UI控件的数据列表。 RefreshGenres似乎没问题,但是看看RefreshMovies,你会立即看到你正在关闭一个未在此方法中打开的连接。也许你在Reader课程中打开它,但那也是你应该关闭它的地方。事实上,conn变得私有化会更好(请记住,UI不必知道数据是来自数据库,文本文件还是用户输入)。此外,Reader的GetGenreList返回一个字符串列表,这是好的,但GetMovieList返回ListViewItem的列表,这是不好的,因为这与您的特定UI实现密切相关。这意味着您的Reader实现无法在WPF或Web应用程序中使用。应使用从Reader获取的普通数据在RefreshMovies中创建ListViewItems。