标签页内的定位按钮不起作用 [英] Positioning button within tabpage not working

查看:199
本文介绍了标签页内的定位按钮不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有按钮和tabcontrol / tabpage组件的表单。该按钮位于表单上,而不是tabcontrol中。我正在尝试将按钮与tabcontrol相关联。我被告知不要使用Controls.Add()方法。



我正在使用Point类来确定tabcontrol的.X .Y。但是,当我单击tabpage index 0时,我将.Left和.Top属性设置为0并且它引用了表单的左上角,而不是tabcontrol。我在网上搜索试图找到一种方法来关联tabcontrol相关的按钮位置,但我找不到参考。使用Controls.Add()是获取按钮引用其与tabcontrol的位置关系的唯一方法吗?



感谢您的帮助。



I have a form with a button and a tabcontrol/tabpage component. The button is on the form, not in the tabcontrol. I'm trying to position the button in relation to the tabcontrol. I was told not to use the Controls.Add() method.

I'm using the Point class to determine the .X .Y of the tabcontrol. However, when I click on tabpage index 0, I set the .Left and .Top properties to 0 and its referencing the top left corner of the form, not the tabcontrol. I searched online trying to find a way to associate the button location in relation to the tabcontrol but I could not find a reference. Is using the Controls.Add() the only way to get the button to reference its position relationship to the tabcontrol?

Thanks for any help.

private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
    Point locPoint = this.Location;//referencing tabControl1???
    int locLeft = locPoint.X;
    int locTop = locPoint.Y;
    if (tabControl1.SelectedIndex == 0)
    {
        button1.Left = 0;// referencing form!
        button1.Top = 0;
    }
    if (tabControl1.SelectedIndex == 1)
    {
        button1.Left = locLeft;
        button1.Top = locTop;
    }
    if (tabControl1.SelectedIndex == 2)
    {
        button1.Left = locLeft;
        button1.Top = locTop;
    }
}

推荐答案

首先解决按钮未定位的问题关于tabcontrol ...



Firstly to address the problem where the button is not being positioned in relation to the tabcontrol ...

private void tabControl1_Selected(object sender, TabControlEventArgs e)
        {
            Point locPoint = this.tabControl1.Location;//referencing tabControl1???
            int locLeft = locPoint.X;
            int locTop = locPoint.Y;

            button1.Left = locLeft;
            button1.Top = locTop;

        }

会这样做。如果你在每个标签上使用不同的位置,你只需要查看selectedIndex - 但是从那里开始简单并构建。

目前这个代码会遮挡标签,所以你不能选择更多,所以考虑改变.Top位置(例如+50)



其次 - 不确定为什么你被告知不要直接把控件放在标签页上 - 你可以像添加到表单一样轻松地动态执行此操作 - clickety [ ^ ]并且你可以获得所有令人讨厌的可见性,具体取决于免费选择哪个选项卡

will do it. You only need to look at the selectedIndex if you're using a different position per tab - but start simple and build up from there.
As it stands this code will obscure the tab so you can't select any more, so consider changing the .Top position (e.g. + 50)

Secondly - not sure why you were told to not put controls directly onto the tabpages - you can do this dynamically just as easily as adding them to the form - clickety[^] and you get all that pesky visibility depending on which tab selected for free


我正在构建一个应用程序作为原型来测试不同标签上组件的定位。我最终会得到几个文本框,几个单选按钮和几个列表框等。其中一些组件将位于tabpage1上,其他组件将位于tabpage2上。



我的计划是使那些将在tabpage1上显示的组件可见并隐藏其余组件。然后在tabpage2上显示其他内容并隐藏tabpage1上显示的内容。我不只是将目标组件添加到目标标签页的原因是因为我的标签页将是动态的,我不会提前知道会有多少,所以我必须动态创建标签页。




请考虑:



0. TabControl如何工作的本质就是你只看到所选TabPage上的控件,所以我无法想象为什么你需要考虑以你所描述的方式显示或隐藏控件。每个TabPage都可以拥有自己的EventHandler,用于每个Control处理的许多常见内容,比如MouseDown,但TabPages不能拥有像KeyPress这样的事件的各自处理程序。



0 。一个。实际上可以将控件从一个TabPage移动到另一个TabPage;这是一个黑客,我自己做了一个只是一个实验,但我看不到任何实际用途,它会引起并发症,imho。



1.一个位于Form上的TabControl有Size,Location,BoundingBox,DisplayRectangle和ClientRectangle,你可以检查的属性,以及那些都将在Form co中在空间中。



2.在TabControl中,每个TabPage都有相同的Size,Location,DisplayRectangle等值:它们都位于co中TabControl的无效空间。



2.a.你可以访问Tab对象的结构来装饰每个TabPage的虚拟顶部,这将在下面提到。



3.你可以调整大小TabControl本身,所有TabPages都会调整大小,但是,你可以永远更改单个TabPage的大小,使其与任何其他TabPage的大小不同。



3a。您可以通过任何方式减少TabPage的有效可见尺寸(黑色面板?),但这是一个奇怪的想法,可能会为用户带来奇怪的体验:fugeddabouttit。



我正在努力了解如何定位一个与tabcontrol相关的组件(我只用一个按钮开始)。如果我能弄明白,那么我可以将它放在任何标签页上,在该标签页中的任何位置。



0.学习定位是一个好事。您需要关注的重要事项包括:



a。了解如何将表格的坐标系统中的点和矩形映射到屏幕的坐标系统,以及控制的坐标系统,反之,这是一件非常好的事情。你需要掌握这些:



a.1。 PointTocreen,PointToClient

a.2。 RectangleToScreen,RectangleToClient



1.在这里你需要向我澄清,或者为自己区分,在CONTROLCollection中定位一个Control是之间的区别表单,以及一个控件,它是我在TabPage的ControlCollection 。



2.如果你想做一些在窗体中,控件位于TabControl和TabPage之上:是的,你可以这样做,是的,你可以确定每个TabPage 的相对位置,因为它被选中使用TabControl的GetTabRect(SelectedIndex)方法(查找),并根据选择的TabPage在表单上移动一个控件。



3.但是,在TabControl顶部的表单上有一个控件,或者在表单上移动以与选择哪个TabPage作为选定的TabPage更改对齐自己:一个非常疯狂的设计理念:)我可以向您展示如何做到的代码,但我认真地建议您不要实现这种类型的Co控制关系,除非有一些令人信服的有机理由这样做(我无法想象一个,但是,谁知道?)。



我是ac#developer告诉他们不要直接将控件放在tabpages上,而是将它们放在表单上,​​然后在需要时将它们移动到tabpage上。



0.我无法猜出给你的建议的意图是什么,但我看到你把每个TabPage上的控件放在每个TabPage上的理由,我看不出有什么理由应该这样做首先在表单上,​​然后在设计时添加到TabPages。如果每个TabPage需要相同的一组控件,只需在设计时在一个TabPage上设置它们,并让它们看起来像你想要的那样,然后将它们复制并粘贴到所有其他TabPages中:最坏的情况是你'我必须将粘贴在Controls中作为一个组移动,以便将它们对齐到你想要的位置,这要归功于Visual Studio有关于粘贴东西的想法。



1也许你的顾问正在考虑这样的情况:在运行时你需要在某些TabPages,一个TabPage或所有TabPages上创建新的控件?这是可能的。



~



让我们考虑在运行时向TabPage添加控件的问题-time:



0.你知道每个TabPage都有相同的坐标空间,左上角为0,0



1.您知道TabPage上已有的每个Control都有位置,大小等。您可以访问的属性确切地知道它在TabPage坐标空间中的位置。



2.作为示例,让我们考虑您希望在运行时在每个TabPage上放置一个新Button,并且您希望它在每个TabPage上的不同y位置基于你定义的一些变量,但是在固定的x位置。



I'm building an app as a prototype to test positioning of components on different tabpages. I will end up with several textboxes, several radio buttons and several listboxes, etc. Some of these components will be positioned on tabpage1 and others on tabpage2.

My plan is to make visible those components that will show on tabpage1 and hide the rest. Then show the others on tabpage2 and hide those shown on tabpage1. The reason I'm not just adding the target components to the target tabpage is because my tabpages will be dynamic and I won't know ahead of time how many there will be so I have to create the tabpages dynamically.


Please consider that:

0. the very nature of how a TabControl works is that you see only the Controls on the selected TabPage, so I can't imagine why you would need to think about showing, or hiding, Controls in the way you've described. Each TabPage can have its own EventHandlers for many of the usual things every Control handles, like MouseDown, but TabPages cannot have their own individual handlers for Events like KeyPress.

0.a. it is possible to actually move Controls from one TabPage to another; it's a hack, and I've done it myself just an experiment, but I can't see any practical use for it, and it invites complications, imho.

1. a TabControl sited on a Form has Size, Location, BoundingBox, DisplayRectangle, and ClientRectangle, Properties that you can inspect, and those will all be in Form co-ordinate space.

2. within the TabControl, each TabPage will have the identical Size, Location, DisplayRectangle, etc., values: they are all located in the co-ordinate space of the TabControl.

2.a. you have some access to the structure of the Tab object that decorates the "virtual top" of each TabPage, which will be mentioned below.

3. you can resize the TabControl itself, and all the TabPages will resize, but, you can never change the size of an individual TabPage so it is different from that of any other TabPage.

3a. you could, through whatever means reduce the effective visible size of a TabPage by whatever means (black panels ?), but that's an odd idea, and probably will lead to a bizarre experience for the user: fugeddabouttit.

I'm trying to develop the understanding of how to position a component (I'm starting with just a button) in relation to a tabcontrol. If I can figure that out, then I can position it on any tabpage, at any position within that tabpage.

0. learning about positioning is a good thing. among the important things you'll want to focus on are:

a. understanding how to map points and rectangles from a Form's co-ordinate system to the Screen's co-ordinate system, and to a Control's co-ordinate system, and the reverse, is a very good thing. you need to master these:

a.1. PointToScreen, PointToClient
a.2. RectangleToScreen, RectangleToClient

1. Here you need to clarify to me, or distinguish for yourself, the difference between positioning a Control which is in the ControlsCollection of a Form, and a Control which is in the ControlCollection of a TabPage.

2. If you want to make some Control, in a Form, be on top of a TabControl and TabPage: yes, you could do that, and, yes, you can determine the relative location of each TabPage as it is selected by using the GetTabRect(SelectedIndex) method of the TabControl (look it up), and move a Control on a Form around based on which TabPage is selected.

3. But, having a Control on the Form on top-of a TabControl, or moving around on the Form to align itself with which TabPage is selected as the selected TabPage changes is: a really "crazy" design idea :) I can show you code for how to do that, but I seriously advise you not to implement this type of Control relationship unless there is some compelling "organic" reason to do so (I can't imagine one, but, who knows ?).

I was told by a c# developer not to put controls on tabpages directly, but to put them on the form and then move them onto the tabpage when you need them.

0. I can't guess what the intent of the advice given to you was, but I see every reason for you to put the Controls on each TabPage necessary for each TabPage, and I can't see any reason why they should be on the Form first, and then added at design-time to the TabPages. If every TabPage needs the same bunch of Controls, just set them at design-time on one TabPage, and get them looking like you want them, and then copy them, and paste them, into all the other TabPages: worst case is you'll have to move the pasted in Controls as a group to get them aligned where you want them thanks to Visual Studio having its own ideas about where to paste things.

1. perhaps your advisor was thinking of the situation where, at run-time you need to created new Controls on certain TabPages, on one TabPage, or on all TabPages ? That is possible.

~

Let's consider the issues in adding a Control to a TabPage at run-time:

0. you know every TabPage will have the same co-ordinate space, with 0,0 at upper-left.

1. you know that every Control already on the TabPage has position, size, etc. Properties you can access to know exactly where it is in TabPage co-ordinate space.

2. as an example, let's consider that you want to place a new Button on every TabPage at run-time, and you wanted it to be at a different y position on each TabPage based on some variable you defined, but at a fixed x location.

private Button btnToBeAdded;

private int btnXLocation = 30;
private int btnStartYLocation = 30;
private int btnYOffset = 40;

private void addButtonsToTabPages_Click(object sender, EventArgs e)
{
    for (int i = 0; i < tabControl1.TabPages.Count; i++)
    {
        // create the Button
        btnToBeAdded = new Button();

        // set visual attributes of the Button
        btnToBeAdded.BackColor = Color.AliceBlue;

        // name it ?, set it's Text
        btnToBeAdded.Name = "addedBtn" + i.ToString();
        btnToBeAdded.Text = "click Me";

        // give the button a tag
        btnToBeAdded.Tag = i;

        // add the Button to the TabPage
        tabControl1.TabPages[i].Controls.Add(btnToBeAdded);

        // set its location
        btnToBeAdded.Location = new Point(btnXLocation, btnStartYLocation + (btnYOffset * i));

        // give it a Click EventHandler
        btnToBeAdded.Click += btnToBeAdded_Click;
    } 
}

private void btnToBeAdded_Click(object sender, EventArgs e)
{
    Button btnClicked = sender as Button;

    // put some code here to be executed when the Button
    // on every TabPage is clicked ?
    // ...

    // make sure you handle every possible index value
    switch (Convert.ToInt32(btnClicked.Tag))
    {
        case 0:
            // call your code if added Button on first TabPage is clicked
            firstTabPageButtonDoSomething();
            break;
        case 1:
            break;
        case 2:
            break;
        // case #n:
            //break;
        default:
            // you have a problem
            throw new IndexOutOfRangeException();
    }
}

private void firstTabPageButtonDoSomething()
{
    MessageBox.Show("Button on first TabPage clicked");
}

讨论:注意添加到每个TabPage的每个Button的Tag属性是如何设置为一个数字值,用于标识TabControl中TabPage的索引。



然后,添加的所有按钮都可以共享相同的'Click EventHandler:使用Tag属性在该EventHandler中...必须将其转换为整数,因为Tag属性是Object类型。然后,您可以触发执行任何您想要每个Button执行的操作。

Discussion: note how the Tag Property of each Button added to each TabPage was set to a numeric value that identified the index of the TabPage in the TabControl.

Then, all Buttons added can share the same 'Click EventHandler: in that EventHandler by using the Tag Property ... had to convert it to an integer because a Tag Property is of type Object ... you can then trigger execution of whatever you want each Button to do.


OP最终删除了第七层面纱:...一个带有文本框和复选框的标签页......将描述备份将如何完成(目的地的一种方式,双向同步或从FTP服务器到PC)...有一个树视图,说明要备份哪些文件夹/文件。...一个标签页配置将我的文档备份为单向类型,另一个标签页配置为备份我的Excel文件夹并同步两种方式等... tabpages将显示完全相同的组件,只需设置为不同的价值。



我正在使用List for class来管理多个tabpages。当我更改tabpages时,我将使用List<>并保存当前的tabpage值,然后加载新选择的tabpage的值。 ...当我点击不同的标签页时,试图将组件从一个标签页移动到另一个标签页。 组件是相同的,我只需要移动它们并重新加载它们的值。




嗯,现在我最后明白你的设计问题是什么:)



是的,如果你在许多可能的场景中只有相同的控制来改变它们的表观值,那么用户会看到什么,或者仅在使用控件时更改他们在代码中执行的操作,或者更改琐碎的事情,例如Button Text是什么:您确实希望只有一组控件,而不是重复控件每个TabPage。



因此,在这种情况下:你对TabControl的唯一真正用途是提供一种方法来改变视图的方面用户,具体取决于他们当前的任务,并且可能在您的代码中根据用户与之交互的当前视图更改您的操作。



还有其他方式你可以在不使用TabControl的情况下处理这个问题,但如果你真的必须使用一个TabControl,然后想一想:



注意:注释和代码遵循地址使用TabControl管理设计挑战的问题:我解决OP在切换到另一个TabPage之前如何在当前TabPage上保存状态的问题,以及它们如何恢复控件的状态时的问题用户切换回上一个TabPage。



1.在第一个TabPage上放置1个面板:将每个TabPage放入的所有控件放入该面板。根据需要设置它们的外观和位置。



2.使用TabControl的Selected Event来跟踪当前选中的TabPage:



2.a.如果之前选择的TabPage不为null,则从前一个TabPage的ControlCollection中删除panel1



2.b.将panel1添加到当前选定的TabPages ControlCollection
The OP finally removed the seventh veil: " ... one tabpage with textboxes and checkboxes ... will describe how the backup will be done (one way to destination, two-way syncing or from FTP server down to PC) ... having a treeview which says what folders/files are to be backed up. ... one tabpage configured to back up My Documents as a one-way type, another tabpage configured to back up my Excel folder and sync both ways, etc. ... tabpages will display the exact same components, just set to different values.

I'm using a List for my class to manage multiple tabpages. When I change tabpages, I will use the List<> and save the current tabpage values and then load in the values for the newly selected tabpage. ... trying to 'move' the components from one tabpage to another as I click on a different tabpage. The components are the same, I just need to move them and reload in their values."


Well, now I finally understand what your design issue is :)

Yes, if you have identical controls in a number of possible scenarios that only change their apparent value, what the user sees, or only change what they do in your code when the controls are used, or change trivial things, like what the Button Text is: you do want to have only one set of Controls, not duplicate the Controls on each TabPage.

So, in this case: the only real use you are making of the TabControl is to provide a way to change the aspects of the view the user sees, depending on their current "task," and, possibly, change, in your code, what you do based on which current view the user is interacting with.

There are other ways you could handle this without using a TabControl, but if you really must use a TabControl, then think about this:

Note: comments and code that follow address only the issue of managing the design challenge using a TabControl: I do not address the issues of how the OP will "save state" of the Controls on the current TabPage before they switch to another TabPage, and how they will restore the "state" of the Controls when the user switches back to the previous TabPage.

1. put 1 panel on the first TabPage: put all the Controls every TabPage will use into that Panel. get their appearance and position set as you wish.

2. use the TabControl's Selected Event to keep track of the current selected TabPage:

2.a. if the previously selected TabPage is not null, then remove panel1 from the previous TabPage's ControlCollection

2.b. add panel1 to the currently selected TabPages ControlCollection
private TabPage currentTabPage;

private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
    if (! (currentTabPage == null)) 
    {
        // here's where you write the code to save
        // whatever information about the previously selected
        // TabPage you want to save
        // ... save whatever ...

        currentTabPage.Controls.Remove(panel1);
    }

    currentTabPage = e.TabPage;

    // see Discussion below
    tabControl1.SuspendLayout();
    currentTabPage.SuspendLayout();
    panel1.SuspendLayout();
    this.SuspendLayout();

    // here's where you write code to configure
    //  Controls in panel1 based on whatever you saved previously
    // ... configure Controls on panel1 to whatever ...

    // for educational purposes only
    Console.WriteLine("selected tabPage: " + currentTabPage.Name);
    Console.WriteLine("selected tabPage's Tab rectangle: "
        + tabControl1.GetTabRect(e.TabPageIndex));
    Console.WriteLine();

    currentTabPage.Controls.Add(panel1);
    // probably unnecessary, but why not ?
    panel1.Dock = DockStyle.Fill;

    // see Discussion below
    tabControl1.ResumeLayout(false);
    tabPage1.ResumeLayout(false);
    panel1.ResumeLayout(false);
    panel1.PerformLayout();
    this.ResumeLayout(false);
    this.PerformLayout();
}

讨论:



0.你在使用布局时所做的那些时髦的东西是什么?



嗯,这正是Windows Form Designer.cs文件处理布局的方式,你看到的可能是过度杀戮,但我把它放进去(希望如此) )这个回复对CP有更多的教育价值。



事实上,即使Form的DoubleBuffered属性设置为'true,并且使用上面的代码,当你从TabPage切换时,你会看到一个轻微的跳跃运行时到TabPage。如果它困扰你,请务必并写下MS:



1.如何管理保存和恢复问题的提示如何状态一组控件现在自动移动到当前选定的TabPage?



1.a.取决于你需要保存的内容:例如,你是否想要保存TreeView文件浏览器的整个状态:这不太可能,因为用户上次打开他的C /.../时有效的文件夹和文件。 ../.../WhatEverFolder可能已经改变了。因此,在这种情况下,您只需要调用保存文件夹路径(字符串)的代码,然后重新加载TreeView。



1.b.无论你创建什么数据结构来保存任何已保存的数据以供重复使用:它的关键显然是TabPage的索引。看一下在我的第一个解决方案中添加的每个控件中设置Tab属性的用法,以及稍后使用该Tab属性在switch / case语句中进行差异操作。



1.c.我的假设是你永远不会想要这样一个复杂的(嵌套的)控件集(面板中包含控件的面板等),你需要以递归方式解析外部面板的全部内容:事实上,如果我看到类似的东西,我会立即认为这是糟糕的设计。所以,在设计时尽你所能标记(通过设置Control的Tag属性)控制你需要保存状态,并将它们存储在List< Control>中。



1.d.另一种可能的设计是定义您自己的继承自WinForms控件的控件,以及用于保存和恢复的额外字段,属性或序列化工具等。

Discussion:

0. what's all that funky stuff you are doing with Layout ?

well, that's exactly the way the Windows Form Designer.cs files handle Layout, and what you see may be "overkill" but I am putting that in so (hopefully) this reply has more educational value on CP.

The fact is that even with the Form's DoubleBuffered property set to 'true, and using the above code, you will see a slight "jump" as you switch from TabPage to TabPage at run-time. Be sure and write MS about that, if it bothers you :)

1. how about a hint on how to manage the issue of saving, and restoring, the "state" of the one set of Controls that are now automatically "moved into" the current selected TabPage ?

1.a. depends on what you need to save: do you, for example, want to save the entire state of the TreeView file-browser: that's unlikely because the folders and files that were valid when the user last opened his C/.../.../.../WhatEverFolder may have changed. So, in that case you'll just need to call the code that takes a saved folder path (string), and reload the TreeView.

1.b. whatever data-structure you do create to hold any saved data for re-use: the "key" to it will be obviously the index of the TabPage. look at the use of setting the Tab property in each control added in my first solution on this thread, and, later, using that Tab property to take differential action in a switch/case statement.

1.c. my assumption is that you'd never want to have such a complex (nested) set of Controls (Panels within Panels that hold Controls, etc.) that you'd need to recursively parse the entire contents of the outer Panel: in fact, if I saw something like that, I'd immediately think it was bad design. so, do whatever you can at design-time to "mark" (by setting the Control's Tag property) Controls you will need to save state from, and store them in a List<Control>.

1.d. another possible design is to define your own Controls that inherit from the WinForms Controls, and extra fields, and properties, or serialization facilities, etc., to use in saving and restoring.


这篇关于标签页内的定位按钮不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆