简体   繁体   English

当用户单击 treeview 节点时,tabcontrol 发生变化

[英]tabcontrol changing when user clicks on treeview node

Here is an overview of my application:这是我的应用程序的概述:

It is basically a cook book.它基本上是一本烹饪书。 The user can create a cookbook and then create recipes within that cookbook.用户可以创建食谱,然后在该食谱中创建食谱。 I have a class CookBook and a class Recipe.我有一本 class 食谱和一本 class 食谱。 CookBook keeps track of what recipes are associated with the cook book and Recipe keeps track of the contents of the recipe. CookBook 跟踪与食谱相关的食谱,Recipe 跟踪食谱的内容。

For the UI, i have a treeview where it will display the recipes that are in the CookBook.对于 UI,我有一个 treeview,它将显示 CookBook 中的食谱。 I have a TabControl that will display the tabs associated with each recipe.我有一个 TabControl,它将显示与每个配方关联的选项卡。 The tabs are dynamically created by the user during run time.选项卡由用户在运行时动态创建。

When the user clicks on one of the recipes, i want the TabControl to show the tabs related to that specific recipe.当用户单击其中一个食谱时,我希望 TabControl 显示与该特定食谱相关的选项卡。 When the user clicks on a different recipe i want the tabs for the previous selection to go away and the tabs of the current selection to appear.当用户单击不同的食谱时,我希望将先前选择的选项卡移至 go 并显示当前选择的选项卡。 (side note: I will be saving the contents of the tab and stuff to a file later, for saving purposes) (旁注:我稍后会将选项卡和内容的内容保存到文件中,以供保存)

I want the Recipe class to contain the details about the TabControl (how many tabs there are for the recipe, title of each of the tabs, contents of the tabs).我希望配方 class 包含有关 TabControl 的详细信息(配方有多少选项卡,每个选项卡的标题,选项卡的内容)。 But i do not want Recipe to be responsible for creating the Tabs or TabControl.但我不希望Recipe 负责创建Tabs 或TabControl。

My questions is, how do i accomplish the bolded section above?我的问题是,我如何完成上面的粗体部分? What are people's opinions and experience with this type of problem?人们对这类问题有何看法和经验? What are the best practices for this type of problem?此类问题的最佳实践是什么?

THANKS!谢谢!

I hope that the following code gives you an idea希望下面的代码能给你一个思路

public Form1()
    {
        InitializeComponent();

        Recipe r1 = new Recipe() { Text = "Re1" };
        Recipe r2 = new Recipe() { Text = "Re2" };
        Recipe r3 = new Recipe() { Text = "Re3" };


        listBox1.Items.Add(r1);
        listBox1.Items.Add(r2);
        listBox1.Items.Add(r3);


        tabControl1.TabPages.Add(new AdvancedTabPage() { Recipe = r1,Text=r1.ToString() });
        tabControl1.TabPages.Add(new AdvancedTabPage() { Recipe = r2, Text = r2.ToString() });
        tabControl1.TabPages.Add(new AdvancedTabPage() { Recipe = r3, Text = r3.ToString() });

        listBox1.SelectedIndexChanged += new EventHandler(listBox1_SelectedIndexChanged);

    }

    void listBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (listBox1.SelectedItem != null)
            foreach (AdvancedTabPage ad in tabControl1.TabPages)
            {
                if (ad.Recipe == listBox1.SelectedItem)
                {
                    tabControl1.SelectedTab = ad;
                    break;
                }
            }

    }

    public class AdvancedTabPage : System.Windows.Forms.TabPage
    {
        public Recipe Recipe{get;set;}


    }

    public class Recipe
    {
        public string Text = "";

        public override string ToString()
        {
            return Text;
        }
    }

This is a WinForms app I assume?这是我假设的 WinForms 应用程序? You've run into the classic UI separation of concerns problem.您遇到了经典的 UI 关注点分离问题。 The way most developers solve this (cleanly) is by implementing something like a document/view model.大多数开发人员(干净地)解决这个问题的方法是实现文档/视图 model 之类的东西。 A loaded term thanks to MFC, but useful nonetheless.多亏了 MFC,一个加载的术语,但仍然有用。

Basically, your Recipe class is the document.基本上,您的食谱 class 就是文档。 The tabs are the view.选项卡是视图。 Create a class that handles the tasks of displaying the Recipe in the tabs (or any other UI container), and use that to handle interaction with the user as well.创建一个 class 来处理在选项卡(或任何其他 UI 容器)中显示配方的任务,并使用它来处理与用户的交互。 The View is typically tightly coupled with the 'container' (which in this case would be the form itself), although that can be abstracted as well.视图通常与“容器”(在这种情况下是表单本身)紧密耦合,尽管它也可以被抽象出来。

D/V in its most basic form is very similar to the MVC pattern, although you can do away with the controller part if your app is simple enough.最基本形式的 D/V 与MVC模式非常相似,尽管如果您的应用程序足够简单,您可以取消 controller 部分。 Here is some light reading on the subject.这里有一些关于这个主题的简单读物。 Don't worry about the fact that it refers to MFC, the approach is the same regardless.不要担心它指的是MFC,无论如何方法都是一样的。 Documentation on MVC might be useful as well, but it tends to focus on web-based apps.有关 MVC 的文档也可能有用,但它往往侧重于基于 Web 的应用程序。

Fun stuff:)好玩的东西:)

One way that I'd approach this is for each Treeview's item to have a reference to the Recipe class it represents.我解决这个问题的一种方法是让每个 Treeview 的项目都引用它所代表的配方 class。 The Treeview will trigger an selection changed event captured on the form where you can extract the Recipe instance. Treeview 将触发在表单上捕获的选择更改事件,您可以在其中提取配方实例。 This will then pass the Recipe instance to the TabControl, which will configure itself based on the Recipe information.然后这会将Recipe 实例传递给TabControl,TabControl 将根据Recipe 信息进行自我配置。

To accomplish this, I'd probably have a custom class derived from Treeview and one from TabControl with methods such as MyTreeview.DisplayCookBook(CookBook book), and MyTabControl.DisplayRecipe(Recipe recipe).为了做到这一点,我可能有一个自定义 class 派生自 Treeview 和一个来自 TabControl 的方法,例如 MyTreeview.DisplayCookBook(CookBook book)和 MyTabControl.DisplayRecipe(Recipe recipe)。 This will encapsulate functionality in their respective containers and will communicate with each other via events, avoiding having a form with 1000 lines of code.这将在各自的容器中封装功能,并通过事件相互通信,避免使用 1000 行代码的表单。

Hope that gives you some direction.希望能给你一些方向。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM