How to display a label in all tabs control - c#

I am using tab control, and there is one label that showing customer's name that I want to display in all three 3 tabs. However, if I put it on tab 1, then it won't show on tab 2 and 3, even thought that the name of the label is unique. Is there a way to do that ? or do I have to create 3 different labels ? thanks a lot.

This might work for you. When changing tabs. Add the label to the TabPage's Controls collection. When adding the label to the new TabPage it gets removed from the previous TabPage so you have to re-add it every time you change tabs.
public partial class Form1 : Form
{
Label label = new Label() { Text = "Hello World" };
public Form1()
{
InitializeComponent();
tabControl1.TabPages[0].Controls.Add(label);
}
private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
e.TabPage.Controls.Add(label);
e.TabPage.Controls.SetChildIndex(label, 0);
}
}

Position label1 in your desired location in the TabPage at design-time, then switch it to the Form in the Load() event using code like this:
private void Form1_Load(object sender, EventArgs e)
{
Point pt = label1.PointToScreen(new Point(0, 0));
label1.Parent = this;
label1.Location = this.PointToClient(pt);
label1.BringToFront();
}

You should put on form 2 panels.
1st panel should have Docking = Top and with height equal to height of your label. Put your label there (on 1st panel).
2nd panel should have Docking = Fill, put your tab control on 2nd panel.

Related

label is not created in other form C# win form

So, my problem is that i have a button in one form that needs to add a label in other form, label has a text that is from main labels textbox, and label has a backcolor that is from color block selected from main form.
private void btnAdd_Click(object sender, EventArgs e)
{
PiezimesLogs log = new PiezimesLogs();//form where the label would be added
Label l = new Label();// creates new label
l.Text = piezimeTxt.Text;
l.BackColor = ColorChange.BackColor;
log.Controls.Add(l);
}
so, this is the code from button that should do everything.
log - other form in which the label should be created.
c# win form
Instead of creating a new label, you could simply add an empty label to your 'target-form'.
Afterwards, you can simply modify the labels' text in order to make it appear.
Regards,
Michael

Why are labels contained within listview stackpanels handled differently by my event handler then regular labels

Was unsure how to word the question but it's as follows.
I have this event handler:
private void labelenterhandler(object sender, EventArgs e)
{
try
{
oldbrush = ((Label)sender).Foreground;
((Label)sender).Foreground = Brushes.White;
((Label)sender).Effect = new System.Windows.Media.Effects.DropShadowEffect
{
Color = new Color { A = 255, R = 0, G = 0, B = 255 },
Direction = 320,
ShadowDepth = 0,
Opacity = 1
};
}
catch
{
}
}
Now, For every label being used as a button I've taken the labelname and gone
labelname.MouseEnter += new MouseEventHandler(labelenterhandler);
Which works as shown here(The mouse is over shipping method) :
After loading a list of classnamehere from the database it clears the listview and I create a stack panel for each item in the list (With labels in it, that have the same exact event handler for MouseEnter)
But when I put my mouse over items on the grid, the border of the label control gets the dropshadoweffect instead of the text like this :
Is there any way of making the actual text get the dropshadoweffect within the listview?
It turns out the labels within the listview had a background color, and the shadow effect only goes on the actual text if the background is transparent.

C# - Creating controls dynamically and accessing them

I'm creating a simple notepad type of application with the tab functionality. I'm creating the TabControl, its TabPages and RichTextBoxes at run-time. I have them instantiated at class scope. And there is a MenuStrip item called New, by clicking that you can add more tab pages.
TabControl tbcEditor = new TabControl();
TabPage tbPage = new TabPage();
RichTextBox rtb = new RichTextBox();
private void frmTextEditor_Load(object sender, EventArgs e)
{
Controls.Add(tbcEditor);
tbcEditor.Dock = DockStyle.Fill;
tbcEditor.TabPages.Add(tbPage);
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
//TabPage tbPage = new TabPage();
//RichTextBox rtb = new RichTextBox();
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
tbcEditor.TabPages.Add(tbPage);
}
The problem I'm facing is a bit difficult to explain. I'll try my best. When the form loads, everything works as expected. The TabControl creates with a TabPage with a RichTextBox added. However if I click that New button to add another page, it goes bonkers. A new TabPage gets created but without a RichTextBox added. No errors are thrown either. If I un-comment out those 2 lines(under MenuItem click event), which creates 2 instances of TabPage and RichTextBox, everything works as I want.
Now my first question is why do I have to make new instances of only those 2 types(TabPage, RichTextBox) again but not TabControl? As you can see in the last line, I can use tbcEditor once again. But not tbPage and rtb.
Sure I can go on declaring them again at local scope but another issue arises then. If I want to say, add copy, paste functionality, I should do something like this,right?
Clipboard.SetDataObject(rtb.SelectedText);
But I can't access rtb since it is declared as local.
I'm very baffled by this so any suggestions, ideas on how to overcome these 2 issues would be greatly appreciated.
Thank you.
If I un-comment out those 2 lines(under MenuItem click event), which creates 2 instances of TabPage and RichTextBox, everything works as I want.
When you uncomment those lines, you are adding the same instance of the rich textbox and tab page to the container panel again which is meaningless. Instead add new controls foreach tabpage. (I hope thats the requirement)
Now my first question is why do I have to make new instances of only those 2 types(TabPage, RichTextBox) again but not TabControl?
TabControl is the parent control which has TabPages as child controls. You can have multiple tabs under one TabControl. So you need not create TabControls other than the tbcEditor you have already added. We do not add container controls more than once (unless its the requirement). Do we need more forms? No, just one form which can hold all the child controls right. Similarly just one TabControl which can hold a collection of TabPages. You would need more TabControls only if you want sub-tabs foreach new tab which I guess is not the requirement..
But I can't access rtb since it is declared as local.
This is no big deal. You can do in two ways:
1) Search for your appropriate control by looping. The SelectedTab property gives what you want.
private void someEvent(object sender, EventArgs e)
{
foreach (Control c in tbcEditor.SelectedTab.Controls)
{
if (c is RichTextBox)
{
Clipboard.SetDataObject(((RichTextBox)c).SelectedText);
break; //assuming u have just one main rtb there
}
}
}
2) Tag each rtb to the tabPage when you create it, and then you can get the tag element of the selected tab page to get the rich text box. I would go for this approach.
Edit: (In general pls make the following changes too to your code):
TabControl tbcEditor = new TabControl();
private void frmTextEditor_Load(object sender, EventArgs e)
{
Controls.Add(tbcEditor);
tbcEditor.Dock = DockStyle.Fill;
AddMyControlsOnNewTab();
}
private void AddMyControlsOnNewTab()
{
TabPage tbPage = new TabPage();
RichTextBox rtb = new RichTextBox();
tbPage.Tag = rtb; //just one extra bit of line.
tbcEditor.TabPages.Add(tbPage);
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
AddMyControlsOnNewTab();
}
Now, you can call it like this:
private void someEvent(object sender, EventArgs e)
{
RichTextBox rtb= (RichTextBox)tbcEditor.SelectedTab.Tag;
Clipboard.SetDataObject(rtb.SelectedText);
//or even better in just a line,
//Clipboard.SetDataObject(((RichTextBox)tbcEditor.SelectedTab.Tag).SelectedText);
}
What you have to consider here is which is the control that you first get and which is the one you do not get. You would get TabPage anyways but not the RichTextBox. So you have to tag RichTextBox to TabPage. You have to cast it since Tag is of type object, so you have to specify which kind of object it is. Finally, this method has the advantage that you need not loop through a list, so its more performant. And that you can have more RichTextBoxes in the TabPage (provided you want to copy text from only one set of RichTextBoxes, one from each TabPage)..
The commented lines are doing just what they are suppposed to do. The code does not associate the Richtextbox with the Tabpage .
TabPage tbPage = new TabPage(); // Creates a new tabpage
RichTextBox rtb = new RichTextBox(); // Creates a new RichtextBox control.
TabControl is a container , so one instance is just fine.
Also see this - http://sujay-ghosh.blogspot.in/2009/03/addingremoving-dynamically-created.html, nothing with do with tabcontrols, but how to create controls on the fly.
Hope this helps .
The code
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
tbcEditor.TabPages.Add(tbPage);
Takes your exisitng textbox, adds it to the exisitng tab page, then adds that existing tab page to the editor. Since this has already been done, nothing happens.
When you add those two lines, you create new instances of the text box and a new tab page, which is exactly what you want. Your latter problem comes, because the newly declared variable rtb hides the one declared in the class -- in a different method you can only access the onde declared in the class (barring getting the control out of the tab)
To get around not being able to access the proper text box, you can maintain them in a list(*) (or some other collection) and refer to the one associated with the currently active tab. For this, you will have to create an event listener to see which tab is activated currectly.
(*) as opposed to having only one
OK you need to create fresh instances of the RichTextBox rathere than trying to add the same instance to each tab.
TabControl tbcEditor = new TabControl();
//Get rid off this line --- TabPage tbPage = new TabPage();
//Get rid off this line --- RichTextBox rtb = new RichTextBox();
List<TabPage> _tabs = new List<TabPage>();
List<RichTextBox> _tbx = new List<RichTextBox>();
private void frmTextEditor_Load(object sender, EventArgs e)
{
Controls.Add(tbcEditor);
tbcEditor.Dock = DockStyle.Fill;
AddNewTab();
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
AddNewTab();
}
private void AddNewTab()
{
//TabPage
var tbPage = new TabPage();
_tabs.Add(tbPage);
//RichTextBox
var rtb = new RichTextBox();
_tbx.Add(rtb);
tbPage.Controls.Add(rtb);
rtb.Dock = DockStyle.Fill;
tbcEditor.TabPages.Add(tbPage);
}
This simply add both the tab and the rtb to a collection which can be accessed by index (can also use Dictionary for named access etc). There are other ways of course, including just nameing the components and looping through for them when required etc.

Data binding to list and dynamically adding controls using Windows Forms

I have a List<Appointment> where an Appointment is.
public class Appointment
{
public string Title { get; set; }
public string Start { get; set; }
public string End { get; set; }
}
I want to dynamically add each list item on a separate line on the form like so:
item.Title + " between" + item.Start + " and " + item.End;
I want to be able to click each item (the text), then with each click it can toggle the colour of the text between red and black (that is, if black it turns red, if red it turns black when you click).
I come from a web background, but I am just struggling with Windows Forms data binding. I've tried with table layout panel but just don't know where to begin with changing the color of an item on click.
PS: If it helps, the number of items in the list will probably not be more than 10.
I've gotten a bit further as per Jamie Ide's comment:
var appts = GetAllCalendarItems();
foreach (var item in appts)
{
Label label = new Label();
label.Text = item.Title + " between" + item.Start + " and " + item.End;
label.Click += new EventHandler(label_Click);
flowLayoutPanel1.Controls.Add(label);
}
...
private void label_Click(object sender, EventArgs e)
{
// This is wrong - what goes here??
((Label)sender).ForeColor = Color.Red;
}
Dynamically laying out Windows Forms is a huge pain. I don't have time to code this but the steps are:
Add FlowLayoutPanel to form as a container
Look through your Appointments and create label controls for each
Add the label controls to the panel's Controls collection
Assign an OnClick handler to each label control to toggle the color
Don't bother with databinding for this.
If you haven't changed the label's initial color from the default, this will toggle it:
private void label1_Click(object sender, EventArgs e)
{
var lbl = (Label)sender;
var toggle = lbl.ForeColor == SystemColors.ControlText;
lbl.ForeColor = toggle ? Color.Red : SystemColors.ControlText;
}
You could add each text field as a member of a Label or List view item. Then handle the "OnClick" or "SelectedIndexChanged" event. To create an an OnClick event handler double click on the control in the design view. Edit the handler like this:
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
listView1.SelectedItems[0].ForeColor = Color.Red;
}
If you are unsure about event handlers, don't be put off they are quite easy, just look them up here perhaps. If the list view is not what you are looking for, try the same approach on a different control.
I guess I can't comment on Jamie's answer, but raklos you can programmatically add the OnClick method by doing:
label.Click += new EventHandler(label_Click);
Visual Studio should auto-generate the stubs for you when you start typing that out.
Something like this could get you started:
private void label_Click(object sender, EventArgs e) { ToggleTextColor((Label)sender); }
private void ToggleTextColor(Control control)
{
var currentColor = control.ForeColor;
control.ForeColor = currentColor == Color.Red ? Color.Black : Color.Red;
}
You can cheat and make create it in a WebBrowserControl.
You will be in familiar ground.
Use ObjectforScripting for WeBbrowser <=> winforms communication.
http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.objectforscripting.aspx

C# Winforms - When are scrollbars for a Control initialized?

Here is the situation:
I am trying to control flowLayoutControl's scroll bar from devexpress controls VerticalScroll.
Now - flowLayoutControl with autoscroll = true. I added a new verticalscroll control and dock it to Right. So now the Devexpress Vertical Scroll control is right on top of FlowLayout scrollbar.
Also the FlowLayoutPanel vertical scroll does not hide when following code is run:
spotWinFlowLayout1.VerticalScroll.Visible = false
I have setup the following event handlers:
private void spotWinFlowLayout1_Resize(object sender, EventArgs e)
{
SetupVerticalScrollBar();
}
private void SetupVerticalScrollBar()
{
vScrollBar1.Minimum = spotWinFlowLayout1.VerticalScroll.Minimum;
vScrollBar1.Maximum = spotWinFlowLayout1.VerticalScroll.Maximum;
vScrollBar1.LargeChange = spotWinFlowLayout1.VerticalScroll.LargeChange;
vScrollBar1.SmallChange = spotWinFlowLayout1.VerticalScroll.SmallChange;
}
private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
{
spotWinFlowLayout1.VerticalScroll.Value = e.NewValue;
}
Everything is working fine except when on form Load there is already a scrollbar on flowLayoutControl,
spotWinFlowLayout1.VerticalScroll.XXX properties not set yet. So both the scrollbars are out of Sync. But as soon as I resize the form both get Sync.
So when is scrollbar for the FlowLayoutPanel initialized?
So when is scrollbar for the
FlowLayoutPanel initialized?
This might sound like a smartalec answer: "When the control is drawn or placed on the form" which is the reason when you adjust the size of the form they are in sync.( they are being drawn again )
The solution is to manually add the scrollbars yourself.

Categories