How to use Document Outline if i create component programmaticlly? - c#

I have MainForm parent mdi window which conatan Menu, ToolBar and StatusStrip created from designer in Visual Studio.
In that MainForm am showing child forms which content was created programmaticly (panels, textboxes, labels, grids etc...)
I have problem when i create DataGridView and set Dock.Top, Dock.Fill my grid is hidden behind parent toolbar.
I can't use Document Outline on programmaticlly created controls.
I try to use BringToFront but again i have the some problem.
To understand better check my screenhsot.
private void InitializeDefaultObjects()
{
/// SPLIT CONTAINER
_splitContainer = new SplitContainer()
{
SplitterDistance = 270,
Panel1MinSize = 270,
Margin = new Padding(15, 15, 15, 15),
Dock = DockStyle.Fill,
BackColor = Color.Gainsboro,
BorderStyle = BorderStyle.None,
Orientation = Orientation.Vertical,
SplitterWidth = 4,
FixedPanel = FixedPanel.Panel1,
RightToLeft = RightToLeft.No,
IsSplitterFixed = false,
Panel1Collapsed = false,
};
_splitContainer.Panel1.Padding = new Padding(5, 5, 5, 5);
_splitContainer.BringToFront();
this.Controls.Add(this._splitContainer);
/// TOOLSTRIP IN SPLIT CONTAINER 1
/// This toolstrip is merged with parent tolstrip
_toolStrip = new System.Windows.Forms.ToolStrip();
_toolStrip.Height = 100;
_toolStrip.Dock = DockStyle.Bottom;
_toolStrip.Visible = false;
_toolStrip.SendToBack();
_toolStrip.BringToFront();
// Toolstrip title
_toolStripTitleLabel = new ToolStripLabel()
{
Text = this.Text,
Alignment = ToolStripItemAlignment.Left,
Font = new Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold),
Image = this.ToolStripTitleImage,
ImageAlign = ContentAlignment.MiddleCenter,
ImageScaling = ToolStripItemImageScaling.SizeToFit
};
// separatar
ToolStripSeparator toolStripSeparator = new ToolStripSeparator() { Alignment = ToolStripItemAlignment.Right };
// Close button
ToolStripButton closeToolStripButton = new ToolStripButton()
{
Text = "Zatvori",
Alignment = ToolStripItemAlignment.Right,
Image = DFMSoftware.Core.Properties.Resource.Close_icon,
TextImageRelation = TextImageRelation.ImageAboveText
};
// Close button event
closeToolStripButton.Click += new EventHandler(closeToolStripButton_Click);
_toolStrip.Items.Add(_toolStripTitleLabel);
_toolStrip.Items.Add(closeToolStripButton);
_toolStrip.Items.Add(toolStripSeparator);
// add toolstripe to splitpanel
this._splitContainer.Panel2.Controls.Add(_toolStrip);
// datagridview
_dataGridView = new System.Windows.Forms.DataGridView();
_dataGridView.Dock = Dock.Fill;
// add grid to splitpanel 2
_splitContainer.Panel2.Controls.Add(_dataGridView);
}
Here in code you can see.
1. I create SplitContainer and set BringToFront() and set Dock.Fill
2. In SplitContainer in Panel2 i add DataGridView with Dock.Fill and again is behind parent.
Am not shure how to slove this does anyone know? THanks
Screensho1

Related

How to apply Border to Button control programmatically using C#

I am creating a Button control using C# as mentioned below in the code. I have created the rounded border for the button style. I am not able to see any property to assign the Border in the button.
var button = new System.Windows.Controls.Button
{
Name = "BtnOk",
Content = "OK",
Height = 20,
Width = 60,
HorizontalAlignment = HorizontalAlignment.Center,
Background = Brushes.DarkGray,
Foreground = Brushes.WhiteSmoke,
Margin = new Thickness(0,0,0,5)
};
Border border = new Border();
border.CornerRadius = new CornerRadius(3);
How can I apply Border in button programatically?
a button cannot aplly a border. a border can decorate a button:
border.Child = button;
usually Buttons already have a Border inside their Template (ControlTemplate). that Border isn't easily accessible - there is no special property of Button class, but that border can be found in visual tree after template was loaded.
additionally that Border can be customized by default style if you put it in Button.Resources. change CorderRadius using Style.Setter:
var button = new System.Windows.Controls.Button
{
Name = "BtnOk",
Content = "OK",
Height = 20,
Width = 60,
HorizontalAlignment = HorizontalAlignment.Center,
Background = Brushes.DarkGray,
Foreground = Brushes.WhiteSmoke,
Margin = new Thickness(0, 0, 0, 5)
};
var style = new Style
{
TargetType = typeof(Border),
Setters = { new Setter { Property = Border.CornerRadiusProperty, Value = new CornerRadius(3) } }
};
button.Resources.Add(style.TargetType, style);
or using object/collection initializers:
var button = new System.Windows.Controls.Button
{
Name = "BtnOk",
Content = "OK",
Height = 20,
Width = 60,
HorizontalAlignment = HorizontalAlignment.Center,
Background = Brushes.DarkGray,
Foreground = Brushes.WhiteSmoke,
Margin = new Thickness(0, 0, 0, 5),
Resources =
{
{
typeof(Border), new Style
{
TargetType = typeof(Border),
Setters =
{
new Setter { Property = Border.CornerRadiusProperty, Value = new CornerRadius(13) }
}
}
}
}
};
if many buttons should have different CornerRadius, changing Button's Template can be a solution. Change template and set CornerRadius as attached dependency property, like shown in this post: Set a property of a nested element in an WPF style
There is indeed a Border element in the default ControlTemplate for the Button but the easiest way to set the CornerRadius property of it, without having to define a custom template, is to wait until the Button has been loaded and then get a reference to it. Try this:
var button = new System.Windows.Controls.Button
{
Name = "BtnOk",
Content = "OK",
Height = 20,
Width = 60,
HorizontalAlignment = HorizontalAlignment.Center,
Background = Brushes.DarkGray,
Foreground = Brushes.WhiteSmoke,
Margin = new Thickness(0, 0, 0, 5)
};
button.Loaded += (ss, ee) =>
{
Border border = button.Template.FindName("border", button) as Border;
if (border != null)
border.CornerRadius = new CornerRadius(3);
};

Manage a ControlCollection - display a new element at the bottom

I need to add a simple at the bottom of an existing view. It is composed of nested panels in a code which I know is not proper. But what I want given my available time is (simple as it sounds) to add my link below what is existing.
In a few words, there is a ControlCollection object being displayed (this.Controls), and I can't locate an element (LinkLabel or TableLayoutPanel) below the other elements.
Here is the minimal existing code :
private void SetAppearance()
{
pnlTitle = new Panel();
pnlTitle.x = ...
this.Controls.Add(pnlTitle);
lblTitle = new Label();
lblTitle.x = ...
pnlTitle.Controls.Add(lblTitle);
tlpnlCountryOfOrigin = new TableLayoutPanel();
tlpnlCountryOfOrigin.x = ...
pnlTitle.Controls.Add(tlpnlCountryOfOrigin);
CountryOfOrigin = new Label();
CountryOfOrigin.x = ...
tlpnlCountryOfOrigin.Controls.Add(CountryOfOrigin, 0, 0);
cbbCountryOrigin = new ComboBoxWithBorders();
cbbCountryOrigin.x = ...
tlpnlCountryOfOrigin.Controls.Add(cbbCountryOrigin, 1, 0);
pnlSupportInfo = new TableLayoutPanel();
pnlSupportInfo.x = ...
this.Controls.Add(pnlSupportInfo);
}
And I am just basically wanting to add my LinkLabel at the bottom of that, with that :
lnkSendLogs = new LinkLabel
{
Font = new Font(ArialBold12px, FontStyle.Regular | FontStyle.Underline),
AutoSize = true,
LinkColor = InfomaxConstants.Colors.Red,
Margin = new Padding(0),
Text = LabelManager.GetLabel("TEXTTOGETLABEL")
};
this.Controls.Add(lnkSendLogs);
Or even with a nested TableLayoutPanel (which I know is not a good practice) :
tlpnlSendLogs = new TableLayoutPanel();
tlpnlSendLogs.ColumnCount = 2;
tlpnlSendLogs.ColumnStyles.Clear();
tlpnlSendLogs.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100));
tlpnlSendLogs.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
lnkSendLogs = new LinkLabel
{
Font = new Font(ArialBold12px, FontStyle.Regular | FontStyle.Underline),
AutoSize = true,
LinkColor = InfomaxConstants.Colors.Red,
Margin = new Padding(0),
Text = LabelManager.GetLabel("TEXTTOGETLABEL")
};
lnkSendLogs.Dock = DockStyle.Fill;
tlpnlSendLogs.Controls.Add(lnkSendLogs, 0, 0);
this.Controls.Add(tlpnlSendLogs);
But the link is always appearing behind other elements, instead of below them.
The question is thus the very basic : How to add a simple LinkLabel appearing at the bottom of a view containing a few elements like Panels and TableLayoutPanels ?
The first problem was that the controls had no location settings, which makes room for random and unwanted things.
Two things to have in mind for the ControlCollection elements:
Locate them
Order them
The thing to know is that the Controls of a ControlCollection are ordered based on their index, AND the one of bigger index will be the one the most at the border of the container (whatever the order in which the children elements anchor are being defined) (https://stackoverflow.com/a/7685041/6617804)
A solution is
1-To set the position of all the ControlCollection elements to the top of their container
pnlTitle.Dock = DockStyle.Top;
pnlSupportInfo.Dock = DockStyle.Top;
tlpnlSendLogs.Dock = DockStyle.Top;
Or the exact same :
pnlTitle.Anchor = (AnchorStyles.Left | AnchorStyles.Top);
pnlSupportInfo.Anchor = (AnchorStyles.Left | AnchorStyles.Top);
tlpnlSendLogs.Anchor = (AnchorStyles.Left | AnchorStyles.Top);
2.1-To arrange the child in the opposite order If we need to (in my case where we want to display them in the opposite order)
this.Controls.SetChildIndex(pnlTitle, 2);
this.Controls.SetChildIndex(pnlSupportInfo, 1);
this.Controls.SetChildIndex(tlpnlSendLogs, 0);
2.2-OR to add them directly in the order they need to be for the display :
this.Controls.Add(tlpnlSendLogs);
this.Controls.Add(pnlSupportInfo);
this.Controls.Add(pnlTitle);
Instead of :
this.Controls.Add(pnlTitle);
this.Controls.Add(pnlSupportInfo);
this.Controls.Add(tlpnlSendLogs);

Buttons do not show up when specifying location property in Windows Forms

I'm trying dynamically add panels within a panel dependent on the count of people in a list using the following code when the form loads:
private void Form1_Load(object sender, EventArgs e)
{
const int xConst = 2;
var people = new List<string>
{
"Person1",
"Person2",
"Person3",
"Person4",
};
var y = 2;
for (var x = 0; x < people.Count; x++)
{
var newpan = new MyPanel
{
BorderStyle = BorderStyle.None,
Height = 25,
Width = panel1.Width - 5,
Location = new Point(xConst, y)
};
var newlbl = new Label
{
BorderStyle = BorderStyle.None,
AutoSize = false,
Text = people[x],
Font = new Font("Segoe UI", 9.5F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(0))),
Size = new Size(75,20),
Location = new Point(newpan.Location.X + 2, newpan.Location.Y + 2),
};
var newbtn = new Button
{
FlatStyle = FlatStyle.Flat,
FlatAppearance = { BorderSize = 0 },
UseVisualStyleBackColor = true,
Text = #"+",
Size = new Size(15,21),
Location = new Point(newpan.Width - 20,newpan.Location.Y - 1),
Font = new Font("Segoe UI", 9.0F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)))
};
newpan.Controls.Add(newlbl);
newpan.Controls.Add(newbtn);
panel1.Controls.Add(newpan);
y += 27;
}
}
The problem is that if I specify the Location property in both the button and the label, only the first iteration of the labels and buttons show up for the Person1 iteration. But, if I leave the Location property out, they all show up. The problem with that is that I have a custom panel that overrides some stuff allowing me to put a customer border and color around the panels, and if I don't specify a location, the labels and buttons aren't positioned correctly on the panel, so it covers my border and looks sloppy.
Can someone help me figure out why this is happening? I've stepped through the program completely and watched all the values I can think of increment accordingly in the watch window. All the panels show up correctly, so I don't understand why their respective labels and buttons don't show up when I specify the location.
Looking at your code I notice that you are setting your newpan height to 25, and its position is offset by 27 with each iteration. You also are using
'Location = new Point(newpan.Location.X + 2, newpan.Location.Y + 2)
to set the location of your button and label within your newpan panel. newpan.Location is referenced in the coordinates of your panel1, your button and label's location is referenced in the coordinates of your newpan panel therefore after the first iteration of your For statement your label and buttons y location value is 29 which is greater than the height of your newpan panel making it not able to be seen, the next iteration after that will be y will be 56 and so forth. Each content control, in this case your panels will have its own coordinate system, the easiest fix would be to do something like this:
'Location = new Point( 2, 2) //for your label
'Location = new Point(newpan.Width - 20, - 1) //for your button
The other alternative is to do like jmcilhinney suggests and make an UserControl with your button and label already in position, you would then create individual instances of it and assign it to your panel1.

Is there an object which has a purpose of indefinite place holding in forms?

I got a form. In this form there is a tab control and there is a menu strip. I would like the tab control to take up the space of the entire form; however, I do not want the menu strip to cover the top of it.
In order to combat this problem. I made a control and I made the panel the same size as the menu strip. I put added the panel control to the menu strip first and then I added the tab control; however, I did not get the desired result. Can someone show me how to get the result I desire?
This is what it looks like without the additional panel.
Here us the code :
public Main()
{
InitializeComponent();
//Panel placeholder = new Panel()
//{
// MaximumSize = menuStrip1.MaximumSize,
// MinimumSize = menuStrip1.MaximumSize,
// Size = menuStrip1.Size,
// Padding = menuStrip1.Padding,
// Visible = true,
//};
//placeholder.Dock = DockStyle.Top;
//Controls.Add(placeholder);
Controls.Add(InitNavigation());
}
TabControl InitNavigation()
{
//Declare All Variables
TabControl control = new TabControl();
TabPage queryPage = new TabPage();
TabPage tablePage = new TabPage();
control.TabPages.Add(queryPage);
control.TabPages.Add(tablePage);
//Customize Table Control
control.Top = menuStrip1.Size.Height;
control.Dock = DockStyle.Fill;
Padding Margin = control.Margin;
MessageBox.Show("" + menuStrip1.Size.Height);
//control.Margin = new Padding(Margin.Left,, Margin.Right, Margin.Bottom);
//Customize Query Tab
queryPage.Text = "Queries";
//Customize Table Page
tablePage.Text = "Tables";
control.Visible = true;
return control;
}
This is what it looks like with the panel
Here is the code:
public Main()
{
InitializeComponent();
Panel placeholder = new Panel()
{
MaximumSize = menuStrip1.MaximumSize,
MinimumSize = menuStrip1.MaximumSize,
Size = menuStrip1.Size,
Padding = menuStrip1.Padding,
Visible = true,
};
placeholder.Dock = DockStyle.Top;
Controls.Add(placeholder);
Controls.Add(InitNavigation());
}
TabControl InitNavigation()
{
//Declare All Variables
TabControl control = new TabControl();
TabPage queryPage = new TabPage();
TabPage tablePage = new TabPage();
control.TabPages.Add(queryPage);
control.TabPages.Add(tablePage);
//Customize Table Control
control.Top = menuStrip1.Size.Height;
control.Dock = DockStyle.Fill;
Padding Margin = control.Margin;
MessageBox.Show("" + menuStrip1.Size.Height);
//control.Margin = new Padding(Margin.Left,, Margin.Right, Margin.Bottom);
//Customize Query Tab
queryPage.Text = "Queries";
//Customize Table Page
tablePage.Text = "Tables";
control.Visible = true;
return control;
}
finally. This last picture just shows that the tabs are in fact there (its the same code as the first code posted except the menu strip visibility is set to false).
Any insight on how to fix this problem would be appreciated
If the fully docked control is underneath a top docked control, try bringing the fully docked control to the front (right click on it in the designer and select bring to front) this should fix it.

Unable to retrieve width of dynamically loaded label with autosize as true

I a bit stuck here. I am trying to dynamically add panel with two labels in it.
The first label must be auto sized and the second label should be positioned to the left of the first one which has a fixed max width and its also auto sized. My code is a follows
pnlSearchResults.SuspendLayout();
Panel pnlRow = new Panel
{
AutoSize = true,
BorderStyle = BorderStyle.FixedSingle,
Padding = new Padding(0),
Margin = new Padding(0),
Top = 0,
Left = 0,
Width = pnlSearchResults.Width - 30,
MaximumSize = new Size(pnlSearchResults.Width - 30, 0)
};
Label lblKey = new Label
{
Name = string.Format("lblKey{0}", 1),
Text = "My label goes here",
AutoSize = true,
TextAlign = ContentAlignment.MiddleLeft,
BorderStyle = BorderStyle.FixedSingle,
Padding = new Padding(0),
Margin = new Padding(0),
Top = 0,
Left = 0,
};
pnlRow.Controls.Add(lblKey);
Label lblValue = new Label
{
Name = string.Format("lblValue{0}", 1),
Text = "And my long text goes here... and it goes on and on and on and on and on and on and on and on and on and on and ...",
AutoSize = true,
Height = 27,
TextAlign = ContentAlignment.MiddleLeft,
BorderStyle = BorderStyle.FixedSingle,
Padding = new Padding(0),
Margin = new Padding(0),
Top = 0,
MaximumSize = new Size(pnlRow.Width - lblKey.Width - 10, 0),
Left = lblKey.PreferredWidth
};
pnlRow.Controls.Add(lblValue);
pnlSearchResults.Controls.Add(pnlRow);
pnlSearchResults.ResumeLayout();
pnlSearchResults.PerformLayout();
I read that calling suspend, resume or perform methods increases performance. And this is what im getting.
As you can see the second label is not getting properly aligned with the first label. Its working fine if i set autosize = false for first label, but I want my first label to be auto sized.
I am not sure what I am missing here, please guide me in the proper way.
This occurs because the label has not yet been drawn and therefore adjusted itself to the correct size. If you want this to work you cannot suspend and resume layouts, you cannot place the controls before the form is shown and you will probably need to call a Refresh in between placing the labels to allow the 1st one to autosize correctly.

Categories