I'm having a MainWindow which is a NavigationWindow. Inside this MainWindow I want to switch in several Pages. One of the Pages has to be dynamically generated by Code, not by XAML. When I had a normal window before, I could add UI components like this:
Button b = new Button();
b.Content = "Hello";
this.AddChild(b);
Or if I added (for example) a StackPanel with this method first, I could add Children to this StackPanel with:
myPanel.Children.Add(b);
However, the Page Class doesn't have a Children Attribute or a AddChild Method.
The only method I found so far is:
AddVisualChild(b);
The page shows but I don't see any components which I added with this method.
So how do I add Children to a WPF-Page correctly?
First of all, the Window.AddChild will throw an exception when you add more than one object to it, because Window is a ContentControl. Page allowes only 1 child .So you set the child using the Page.Content property. So you want to add a container to your Page and then add children to the container.
For example:
Button b = new Button();
b.Content = "Hello";
StackPanel myPanel = new StackPanel();
myPanel.Children.Add(b);
this.Content = myPanel;
I'm not really sure if this works for you but you could try to set the content of a page to a user control. E.g. use a StackPanel and add all the children to it. After that you set the content of the Page to the Stackpanel.
Here is an lazy example in the constructor of a MainWindow.
public MainWindow()
{
InitializeComponent();
StackPanel panel = new StackPanel();
Button b1 = new Button {Content = "Hello"};
Button b2 = new Button {Content = "Hi"};
panel.Children.Add(b1);
panel.Children.Add(b2);
Page page = new Page {Content = panel};
this.Content = page;
}
Related
How do I create a simple form that has a MenuStrip at the top and a TabControl filling all of the remaining space?
If I go with DockStyle.Top/DockStyke.Fill tabControl fills whole form regardless of MenuStrip:
public MainWindow()
{
initializeComponent();
}
private void initializeComponent()
{
MenuStrip mainMenu = new MenuStrip();
mainMenu.Dock = DockStyle.Top;
TabControl tabs = new TabControl();
tabs.Dock = DockStyle.Fill;
TabPage test = new TabPage("test");
tabs.Controls.Add(test);
Controls.Add(mainMenu);
Controls.Add(tabs);
}
You should change the z-order of mainMenu or tabs. For example you can call:
mainMenu.SendToBack();
//Or
//tabs.BringToFront();
After adding controls to the controls collection.
Another approach through designer, without writing code manually, so your changes will affect design time too
Use Document outline tab and arrange control's hierarchy with your requirements
View -> Other Windows -> Document outline or CTRL+ALT+T
I can create a new element of type Page in code behind, but I want to add children elements of type UIElement as I would to a Grid like: myGrid.Children.Add(myUIElement);
I don't have the Children property and setting the Content property does not work.How can I achieve this?
UPDATE:
This is what I have so far, but does not work:
Page myNewPage = new Page();
Grid myGrid = new Grid();
TextBlock myText = new TextBlock();
myText.Text = "I am a TextBlock!";
myGrid.Children.Add(myText);
myNewPage.Content = myGrid;
Frame.Navigate(myNewPage.GetType());
A Page can host a single UIElement in its Content property. To add several children, you have to do it like you would do it in XAML: add a panel that can contain and layout several children and add your elements to that panel.
In your question you talk about a grid called myGrid. You could add and layout your items in myGrid and then set myGrid as yourPage.Content.
Your code correctly builds the page. The problem with your code is that your Frame is navigating to a new instance of Page that is not the one that you created. Frame creates a new instance of the type that you pass as a parameter.
If you want to create a page fully in code, you can simply create class that extends Page and build the page in its constructor:
public class MyPage : Page
{
public MyPage()
{
this.BuildPage();
}
private void BuildPage()
{
var panel = new StackPanel();
panel.Children.Add(new TextBlock { Text = "Hello" });
panel.Children.Add(new TextBlock { Text = "World" });
this.Content = panel;
}
}
That's, after all, what the InitializeComponent method does in pages created in XAML.
Is there a way to add a control like in Win Forms C# Button b = new Button(); and then add it just like Form1.Controls.Add(b);
I can't do this in WPF because I don't have a Controls attribute in the Window class. How can I do this. I read this of just putting a Panel, dock it to fill and then there I use this:
myPanel.Children.Add(b);
But then it comes to me again. How do I create and add a Panel and dock it to fill?
If I use Panel p = new Panel(); it marks error. And how do I add the panel to my MainWindow?
You can add a stackpanel to window like below.
StackPanel myPanel = new StackPanel();
myWindow.Content = myPanel;
Like #HighCore said below, it is not cleaner to add controls in codebehind. Use XAML wherever it is possible and avoid adding controls in code behind
You can create any structure in C# as you can in XAML.
var p = new Panel();
Above doesn't work because Panel is an abstract class. You can, however do:
var p = new StackPanel();
var g = new Grid();
var wp = new WrapPanel();
var dp = new DockPanel();
//Etc.
See all panels here: http://msdn.microsoft.com/en-us/library/system.windows.controls.panel(v=vs.110).aspx
<Window ...>
<StackPanel>
<TextBox/>
</StackPanel/>
</Window>
is equivalent with (from your MainWindow.xaml.cs):
var sp = new StackPanel();
sp.Children.Add(new TextBox);
Content = sp;
EDIT: Just to be clear, you ONLY want to create your UI in C# if it is dynamic in nature. If you know which fields will be there, always, use XAML. It is the HTML of WPF. Coding everything in the code-behind is the web-design equivalent of sending a blank HTML file and creating everything in JavaScript.
I am working on an ERP project. it is a button on treeView box and when it is clicking on a button in treeView it must create a Tab with its content (content which is defined-designed before).
I can add a tab programically but how can I design its content?
Adding this to your click event of your treeview should do what you are after:
var contentControl = new ContentControl (); //This is what we will put all your content in
contentControl.Dock = DockStyle.Fill;
var page = new TabPage("Tab Text"); //the title of your new tab
page.Controls.Add(contentControl); //add the content to the tab
TabControl1.TabPages.Add(page); //add the tab to the tabControl
To your project, add a new UserControl called ContentControl (or whatever you need, just using this in my example), and fill it with all the contents you want to appear in your tab.
You have few solutions, the simplest one is to create TabPage, create desired Controls, set up their properties (i.e. Size, Location, Text etc.), add them to the TabPage and then add TabPage to the TabControl.
TabPage tp = new TabPage();
//create controls and set their properties
Button btn1 = new Button();
btn1.Location = new Point(10,10);
btn1.Size = new System.Drawing.Size(30,15);
//add control to the TabPage
tp.Controls.Add(btn1);
//add TabPage to the TabControl
tabControl1.TabPages.Add(tp);
the second solution is to override TabPage in your class, for instance CustomTabPage where you will set up controls in the constructor of the class. Then, when you want to add new TabPage, create your CustomTabPage instance and add it to the TabControl.
public class CustomTabPage : TabPage
{
public CustomTabPage()
{
//create your Controls and setup their properties
Button btn1 = new Button();
btn1.Location = new Point(20, 20);
btn1.Size = new System.Drawing.Size(40, 20);
//add controls to the CustomTabPage
this.Controls.Add(btn1);
}
}
//Create CustomTabPage
CustomTabPage ctp = new CustomTabPage();
tabControl1.TabPages.Add(ctp);
the third solution (the best but the most complicated) is to create your desired UserControl with everything you want on it (you can use Designer help), then create an instance of your UserControl, Create a TabPage and add UserControl on the TabPage. Then add TabPage to the TabControl.
public partial class CustomControlForTabPage : UserControl
{
public CustomControlForTabPage()
{
InitializeComponent();
}
}
//Create CustomControl
TabPage tp = new TabPage();
CustomControlForTabPage ccftp = new CustomControlForTabPage();
//set properties you like for your custom control
tp.Controls.Add(ccftp);
tabControl1.TabPages.Add(ctp);
Add a new user control to the project then use the designer to do controls/layout, then when you click all you do is add a new instance of the user control to the tab - probably docked to fill the tab unless your form's size is fixed.
I have a panel of labels, buttons and image that I wish to put into a flow layout panel.
As seen in some tutorial, I understand that it is possible to auto align new and additional buttons into a flow layout panel.
what I would like to ask is that is it possible to put a panel WITHIN a flow layout panel and call multiple instances of the same panel to appear within the flow layout panel.
My panel code would be
this.panelNotification.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panelNotification.Controls.Add(this.button1);
this.panelNotification.Controls.Add(this.lblImage);
this.panelNotification.Controls.Add(this.lblName);
this.panelNotification.Controls.Add(this.lblLinkName);
this.panelNotification.Controls.Add(this.lblLinkLocation);
this.panelNotification.Controls.Add(this.lblLocation);
this.panelNotification.Location = new System.Drawing.Point(3, 3);
this.panelNotification.Name = "panelNotification";
this.panelNotification.Size = new System.Drawing.Size(506, 100);
this.panelNotification.TabIndex = 17;
So is it possible to include the whole panel into a flow layout panel? if yes, how do i do it. thank you.
Yes, you can put a Panel into a FlowLayoutoutPanel.
No, you can't put a control several times into a FlowLayoutoutPanel (in fact you can, but it is only displayed once).
But what you could do is writing some kind of Factory-Method that creates a new Panel with new Buttons/Labels/other Controls etc. every time you call it, and add these new instances to your FlowLayoutpanel. Something like this:
public class Form1
{
private Panel CreateNotificationPanel()
{
var p = new Panel { BackColor = Color.Red };
p.Controls.Add(new Button { Text = "Test" });
return p;
}
private void Form1_Load(System.Object sender, System.EventArgs e)
{
var flp = new FlowLayoutPanel { Dock = DockStyle.Fill };
flp.Controls.Add(CreateNotificationPanel());
flp.Controls.Add(CreateNotificationPanel());
flp.Controls.Add(CreateNotificationPanel());
this.Controls.Add(flp);
}
public Form1() { Load += Form1_Load; }
}
Another (and problably better) approach would be to create a UserControl that contains your Buttons/Labels/etc. instead of using a panel and adding all controls manually. Just create with the Designer and add new instances of the UserControl to the FlowLayoutPanel.