Skip to main content

Containers

Table of content

Controls

Any control can be a container. Indeed a control can have several children. For more information, see Parent and children.

While this is possible, we generally prefer to use defined containers that have specific properties to handle child controls.

Standard containers

These containers use location, size, auto_size, anchor and dock for children controls.

For more information, see Size and location properties and Position and layout of controls.

Fixed layout panel

The fixed_layout_panel is used to group collections of fixed aligned controls.

Example

The following example demonstrates the use of fixed_layout_panel container.

#include <xtd/xtd>

using namespace xtd::forms;

class form1 : public form {
public:
form1() {
client_size({400, 200});

panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});

button1.location({10, 10});
button1.text("button 1");

button2.location({10, 55});
button2.text("button 2");

button3.location({10, 100});
button3.text("button 3");

button4.location({10, 145});
button4.text("button 4");
}

private:
fixed_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

Group box

group_box represents a Windows control that displays a frame around a group of controls with an optional caption.

Example

The following example demonstrates the use of group_box container.

#include <xtd/xtd>

using namespace xtd::forms;

class form1 : public form {
public:
form1() {
client_size({400, 200});

group_box1.parent(*this).dock(dock_style::fill);
group_box1.controls().push_back_range({button1, button2, button3, button4});

button1.location({10, 10});
button1.text("button 1");

button2.location({10, 55});
button2.text("button 2");

button3.location({10, 100});
button3.text("button 3");

button4.location({10, 145});
button4.text("button 4");
}

private:
group_box group_box1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

Panel

panel is used to group collections of controls.

The following example demonstrates the use of panel container.

#include <xtd/xtd>

using namespace xtd::forms;

class form1 : public form {
public:
form1() {
client_size({400, 200});

panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});

button1.location({10, 10});
button1.text("button 1");

button2.location({10, 55});
button2.text("button 2");

button3.location({10, 100});
button3.text("button 3");

button4.location({10, 145});
button4.text("button 4");
}

private:
fixed_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

popup_panel represents a special type of panel container that can be used for context_menu, combo_box popups and more.

Example

The following example demonstrates the use of popup_panel container.

#include <xtd/xtd>

using namespace xtd;
using namespace xtd::drawing;
using namespace xtd::forms;

class form1 : public form {
public:
form1() {
text("Popup panel example");
client_size({300, 100});
controls().push_back_range({button1, popup_panel1});

list_box1.parent(popup_panel1);
list_box1.dock(dock_style::fill);
list_box1.items().push_back_range({{"clear", button_images::from_name("weather-clear")}, {"clear night", button_images::from_name("weather-clear-night")}, {"few clouds", button_images::from_name("weather-few-clouds")}, {"few clouds night", button_images::from_name("weather-few-clouds-night")}, {"fog", button_images::from_name("weather-fog")}, {"overcast", button_images::from_name("weather-overcast")}, {"severe alert", button_images::from_name("weather-severe-alert")}, {"showers", button_images::from_name("weather-showers")}, {"showers scattered", button_images::from_name("weather-showers-scattered")}, {"snow", button_images::from_name("weather-snow")}, {"storm", button_images::from_name("weather-storm")}});
list_box1.selected_index(0);
list_box1.click += [&] {
button1.text(list_box1.selected_item().value());
button1.image(as<image>(list_box1.selected_item().tag()));
popup_panel1.hide();
};

button1.location({10, 10});
button1.size({160, 50});
button1.image_align(content_alignment::top_center);
button1.text_align(content_alignment::bottom_center);
button1.text(list_box1.selected_item().value());
button1.image(as<image>(list_box1.selected_item().tag()));
button1.click += [&] {
popup_panel1.show();
};

popup_panel1.location(button1.location());
popup_panel1.width(button1.width());
}

private:
button button1;
list_box list_box1;
popup_panel popup_panel1;
};

auto main() -> int {
application::run(form1 {});
}

Splitter panel

splitter_panel represents a panel that is associated with a split_container.

Coming soon...

Tab page

tab_page represents a single tab page in a tab_control.

Example

The following example demonstrates the use of tab_page container.

#include <xtd/xtd>

using namespace xtd::forms;

class form1 : public form {
public:
form1() {
text("Tab control example");
controls().push_back(tab_control1);
client_size({390, 270});

tab_control1.location({10, 10});
tab_control1.size({370, 250});
tab_control1.anchor(anchor_styles::left | anchor_styles::top | anchor_styles::right | anchor_styles::bottom);

tab_page1.parent(tab_control1);
tab_page1.text("Tab page 1");

label1.dock(dock_style::fill);
label1.parent(tab_page1);
label1.text("label1");
label1.text_align(xtd::forms::content_alignment::top_left);

tab_page2.parent(tab_control1);
tab_page2.text("Tab page 2");

label2.dock(dock_style::fill);
label2.parent(tab_page2);
label2.text_align(xtd::forms::content_alignment::middle_center);
label2.text("label2");

tab_page3.parent(tab_control1);
tab_page3.text("Tab page 3");

label3.dock(dock_style::fill);
label3.parent(tab_page3);
label3.text_align(xtd::forms::content_alignment::bottom_right);
label3.text("label3");
}

private:
tab_control tab_control1;
tab_page tab_page1;
tab_page tab_page2;
tab_page tab_page3;

label label1;
label label2;
label label3;
};

auto main() -> int {
application::run(form1 {});
}

Remarks

Layout containers

The layout containers manage the layout of child controls. Unlike standard containers, they manage the size, position and layout of child controls and do not use user-defined child control properties.

Remarks

Layout containers can use the dock or anchor to position themselves in the parent control (Usually we use dock(dock_style::fill)).

On the other hand, child controls of layout panel cannot use the dock or anchor properties because it is the layout panel that decides how to display them according to the chosen options.

Flow layout panel

flow_layout_panel is used to group collections of fixed aligned controls.

Coming soon...

Horizontal layout panel

horizontal_layout_panel is used to group collections of horizontally aligned controls.

Horizontal layout panel styles

For each child control of horizontal_layout_panel an horizontal_layout_style style is associate. You can specify for each chid control the layout style to the layout container by the method control_layout_style. If you don't specify the layout style, it use the style by default.

An horizontal_layout_style is composed of :

  • content_alignment : One of the content_alignment values. The default is middle_center.
    • top_left : Content is vertically aligned at the top, and horizontally aligned on the left.
    • top_center : Content is vertically aligned at the top, and horizontally aligned at the center.
    • top_right : Content is vertically aligned at the top, and horizontally aligned on the right.
    • middle_left : Content is vertically aligned in the middle, and horizontally aligned on the left.
    • middle_center : Content is vertically aligned at the middle, and horizontally aligned at the center.
    • middle_right : Content is vertically aligned at the middle, and horizontally aligned on the right.
    • bottom_left : Content is vertically aligned in the bottom, and horizontally aligned on the left.
    • bottom_center : Content is vertically aligned at the bottom, and horizontally aligned at the center.
    • bottom_right : Content is vertically aligned at the bottom, and horizontally aligned on the right.
  • exapend : A flag indicating if control is expanded to its containing layout container. The default is false.
  • size_type : One of the size_type values that specifies how layout container of user interface (UI) elements should be sized relative to their container. The default is auto_size.
    • auto_size : The control should be automatically sized to share space with its peers.
    • absolute : The control should be sized to an exact number of pixels. (Style by default)
    • percent : The control should be sized as a percentage of the parent container.
  • width : The prefered width in pixel or percent depending the size_type. The default is std::nullopt.

Remarks

If you don't set expand to true and you set the height of the control. the horizontal_layout_panel will take this into account. But not the width.

Examples

The following example shows how to create a horizontal_layout_panel with children that have a default style.

#include <xtd/xtd.forms.h>

using namespace xtd;
using namespace xtd::forms;

class form1 : public form {
public:
form1() {
client_size({400, 200});

panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});

button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}

private:
horizontal_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

The following example shows how to create a horizontal_layout_panel whose children must have a size corresponding to a percentage of the parent container.

#include <xtd/xtd.forms.h>

using namespace xtd;
using namespace xtd::forms;

class form1 : public form {
public:
form1() {
client_size({400, 200});

panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});

panel1.control_layout_style(button1, horizontal_control_layout_style{.15f, size_type::percent});
panel1.control_layout_style(button2, horizontal_control_layout_style{.35f, size_type::percent});
panel1.control_layout_style(button3, horizontal_control_layout_style{.35f, size_type::percent});
panel1.control_layout_style(button4, horizontal_control_layout_style{.15f, size_type::percent});

button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}

private:
horizontal_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

The following example shows how to create a horizontal_layout_panel whose children must have a size corresponding to a abosulte value in pixels and set expand to true.

#include <xtd/xtd.forms.h>

using namespace xtd;
using namespace xtd::forms;

class form1 : public form {
public:
form1() {
client_size({400, 200});

panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});

panel1.control_layout_style(button1, horizontal_control_layout_style{75, size_type::absolute, true});
panel1.control_layout_style(button2, horizontal_control_layout_style{125, size_type::absolute, true});
panel1.control_layout_style(button3, horizontal_control_layout_style{125, size_type::absolute, true});
panel1.control_layout_style(button4, horizontal_control_layout_style{75, size_type::absolute, true});

button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}

private:
horizontal_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

Table layout panel

table_layout_panel is used to group collections of fixed aligned controls.

Coming soon...

Vertical layout panel

vertical_layout_panel is used to group collections of verticaly aligned controls.

Vertical layout panel styles

For each child control of vertical_layout_panel an vertical_layout_style style is associate. You can specify for each chid control the layout style to the layout container by the method control_layout_style. If you don't specify the layout style, it use the style by default.

An vertical_layout_style is composed of :

  • content_alignment : One of the content_alignment values. The default is middle_center.
    • top_left : Content is vertically aligned at the top, and horizontally aligned on the left.
    • top_center : Content is vertically aligned at the top, and horizontally aligned at the center.
    • top_right : Content is vertically aligned at the top, and horizontally aligned on the right.
    • middle_left : Content is vertically aligned in the middle, and horizontally aligned on the left.
    • middle_center : Content is vertically aligned at the middle, and horizontally aligned at the center.
    • middle_right : Content is vertically aligned at the middle, and horizontally aligned on the right.
    • bottom_left : Content is vertically aligned in the bottom, and horizontally aligned on the left.
    • bottom_center : Content is vertically aligned at the bottom, and horizontally aligned at the center.
    • bottom_right : Content is vertically aligned at the bottom, and horizontally aligned on the right.
  • exapend : A flag indicating if control is expanded to its containing layout container. The default is false.
  • size_type : One of the size_type values that specifies how layout container of user interface (UI) elements should be sized relative to their container. The default is auto_size.
    • auto_size : The control should be automatically sized to share space with its peers.
    • absolute : The control should be sized to an exact number of pixels. (Style by default)
    • percent : The control should be sized as a percentage of the parent container.
  • width : The prefered width in pixel or percent depending the size_type. The default is std::nullopt.

Remarks

If you don't set expand to true and you set the width of the control. the vertical_layout_panel will take this into account. But not the height.

Examples

The following example shows how to create a vertical_layout_panel with children that have a default style.

#include <xtd/xtd.forms.h>

using namespace xtd;
using namespace xtd::forms;

class form1 : public form {
public:
form1() {
client_size({200, 400});

panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});

button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}

private:
vertical_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

The following example shows how to create a vertical_layout_panel whose children must have a size corresponding to a percentage of the parent container.

#include <xtd/xtd.forms.h>

using namespace xtd;
using namespace xtd::forms;

class form1 : public form {
public:
form1() {
client_size({200, 400});

panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});

panel1.control_layout_style(button1, vertical_control_layout_style{.15f, size_type::percent});
panel1.control_layout_style(button2, vertical_control_layout_style{.35f, size_type::percent});
panel1.control_layout_style(button3, vertical_control_layout_style{.35f, size_type::percent});
panel1.control_layout_style(button4, vertical_control_layout_style{.15f, size_type::percent});

button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}

private:
vertical_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

The following example shows how to create a vertical_layout_panel whose children must have a size corresponding to a abosulte value in pixels and set expand to true.

#include <xtd/xtd.forms.h>

using namespace xtd;
using namespace xtd::forms;

class form1 : public form {
public:
form1() {
client_size({200, 400});

panel1.parent(*this).dock(dock_style::fill);
panel1.controls().push_back_range({button1, button2, button3, button4});

panel1.control_layout_style(button1, vertical_control_layout_style{75, size_type::absolute, true});
panel1.control_layout_style(button2, vertical_control_layout_style{125, size_type::absolute, true});
panel1.control_layout_style(button3, vertical_control_layout_style{125, size_type::absolute, true});
panel1.control_layout_style(button4, vertical_control_layout_style{75, size_type::absolute, true});

button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}

private:
vertical_layout_panel panel1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

Specific containers

Collapsible panel

collapsible_panel is used to group collections of controls in a collapsible panel.

coming soon...

Split container

split_container represents a control consisting of a movable bar that divides a container's display area into two resizable panels.

Remarks

The child control for the split_container are splitter_panel.

coming soon...

Tab control

tab_control manages a related set of tab pages.

Remarks

The child controls for the tab_control are tab_page.

Example

The following example demonstrates the use of tab_control container.

#include <xtd/xtd>

using namespace xtd::forms;

class form1 : public form {
public:
form1() {
text("Tab control example");
controls().push_back(tab_control1);
client_size({390, 270});

tab_control1.location({10, 10});
tab_control1.size({370, 250});
tab_control1.anchor(anchor_styles::left | anchor_styles::top | anchor_styles::right | anchor_styles::bottom);

tab_page1.parent(tab_control1);
tab_page1.text("Tab page 1");

label1.dock(dock_style::fill);
label1.parent(tab_page1);
label1.text("label1");
label1.text_align(xtd::forms::content_alignment::top_left);

tab_page2.parent(tab_control1);
tab_page2.text("Tab page 2");

label2.dock(dock_style::fill);
label2.parent(tab_page2);
label2.text_align(xtd::forms::content_alignment::middle_center);
label2.text("label2");

tab_page3.parent(tab_control1);
tab_page3.text("Tab page 3");

label3.dock(dock_style::fill);
label3.parent(tab_page3);
label3.text_align(xtd::forms::content_alignment::bottom_right);
label3.text("label3");
}

private:
tab_control tab_control1;
tab_page tab_page1;
tab_page tab_page2;
tab_page tab_page3;

label label1;
label label2;
label label3;
};

auto main() -> int {
application::run(form1 {});
}

User container

xtd is flexible and complete enough to create your own container without much effort.

Own horizontal stack panel

The following example show how to make your own horizontal stack panel esasily with overloading on_layout method.

#include <xtd/xtd.forms.h>

using namespace xtd;
using namespace xtd::forms;

class horizontal_stack_panel : public panel {
protected:
void on_layout(const event_args& e) override {
panel::on_layout(e);
auto left = 0;
for (auto control : controls()) {
control.get().left(left).height(client_size().height());
left += control.get().width();
}
}
};

class form1 : public form {
public:
form1() {
client_size({400, 200});

panel1.parent(*this).size({300, 35});
panel1.controls().push_back_range({button1, button2, button3, button4});

button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}

private:
horizontal_stack_panel panel1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

Own vertical stack panel

The following example show how to make your own vertical stack panel esasily with dock and overloading on_control_added method.

#include <xtd/xtd.forms.h>

using namespace xtd;
using namespace xtd::forms;

class vertical_stack_panel : public panel {
protected:
void on_control_added(const control_event_args& e) override {
panel::on_control_added(e);
e.control().dock(dock_style::top);
}
};

class form1 : public form {
public:
form1() {
client_size({400, 200});

panel1.parent(*this).size({100, 150});
panel1.controls().push_back_range({button4, button3, button2, button1});

button1.flat_style(xtd::forms::flat_style::popup).text("button 1");
button2.flat_style(xtd::forms::flat_style::popup).text("button 2");
button3.flat_style(xtd::forms::flat_style::popup).text("button 3");
button4.flat_style(xtd::forms::flat_style::popup).text("button 4");
}

private:
vertical_stack_panel panel1;
button button1;
button button2;
button button3;
button button4;
};

auto main() -> int {
application::run(form1());
}

See also