Learn Universal Windows Programming Via Modern C++ (RelativePanel)

Here, I have explained how to implement RelativePanel control in C++/WinRT.

Before reading this article, I highly recommend reading the previous parts of the series.

In this article, we are going to learn about RelativePanel control in Modern C++/WinRT. UWP Control Panels is divided into the following two types,
  1. Linear pattern or Panel.
  2. Non-Liner pattern or Panel.

Linear Pattern

In a Linear Pattern, all the controls should be either Horizontal or Vertical.

For example, a StackPanel.

Non-Linear pattern

In a Non-Linear pattern, all the controls are aligned in any order with relationship to other controls, like top or bottom or right or left etc.

Now, I am going to explain how to implement the Non-Linear pattern. RelativePanel control is called Non-Linear pattern also.

Relative panel

Each control has a relationship with other controls with any relationship (but not a circular dependency).

ReleativePanel Properties

Children

All the itemcontrols have to be added to the children property. "Children" is a UIElementCollection container and by default, all the controls are added into the zero-index order. "Append properties" is used to add the Controls into the container.

  1. RelativePanel RPanel;  
  2.     RPanel.Children().Append(txtTop);  
  3.     RPanel.Children().Append(txtBottom);  
  4.     RPanel.Children().Append(txtLeft);  
  5.     RPanel.Children().Append(txtRight);  
  6.     RPanel.Children().Append(txtHorCenter);  
  7.     RPanel.Children().Append(txtVertical);  
  8.     RPanel.Children().Append(txtRightOf);  
  9.     RPanel.Children().Append(txtLeftOf);  
  10.     RPanel.Children().Append(txtAbove);  
  11.     RPanel.Children().Append(txtBelow);  
  12.     RPanel.Children().Append(txtHeader);  

Properties' position inside the Panel control

 
  • The complete box is a Relative panel.
  • Inside boxes are child controls.
  • Arrow is specified as Alignment and Position of the controls.

A RelativePanel is a Parent control, all inside controls are child controls.

There are generally the following two types of relationships,

  1. Parent to child.
  2. Child to child.

Parent -> Child: All panel properties are parent types.

Set the parent related controls, pass the control name, & set as true. It's attached to the parent control.

Parent related APIs

  1. RelativePanel.SetAlignTopWithPanel(control,true);  
  2. RelativePanel.SetAlignBottomWithPanel(control, true);  
  3. RelativePanel.SetAlignLeftWithPanel(control, true);  
  4. RelativePanel.SetAlignRightWithPanel(control, true);  
  5. RelativePanel.SetAlignVerticalCenterWithPanel(control, true);  
  6. RelativePanel.SetAlignHorizontalCenterWithPanel(control,true); 

Child relationship

Child to child (other than panel relationship, properties consider the child to child properties).

Below APIs are used to set the Child to Child relationship. For child relationship APIs, first we need to pass the child argument as first, which child we are attaching (Parent) that should be second arguments.

Child APIs

  1. RelativePanel.SetRightOf(ChildControl, PropertyValue::CreateInspectable(ParentControl));  
  2. RelativePanel.SetLeftOf(ChildControl, PropertyValue::CreateInspectable(ParentControl));  
  3. RelativePanel.SetAbove(ChildControl, PropertyValue::CreateInspectable(ParentControl));  
  4. RelativePanel.SetBelow(ChildControl, PropertyValue::CreateInspectable(ParentControl));  

All the alignment properties are high-priority and the remaining (position) properties are low-priority.

 

Each control's relation with other controls is something. If we did not provide the relative properties, then the first control aligns with the default position and the next controls overwrite the previous control and always set the relative controls. For each control, one or more relationship depends on the requirements. 

Sample code to implement RelativePanel in Modern C++ / WinRT
  1. #include "pch.h"  
  2.   
  3. using namespace winrt;  
  4. using namespace Windows::ApplicationModel;  
  5. using namespace Windows::ApplicationModel::Activation;  
  6. using namespace Windows::Foundation;  
  7. using namespace Windows::UI;  
  8. using namespace Windows::UI::Xaml;  
  9. using namespace Windows::UI::Xaml::Controls;  
  10. using namespace Windows::UI::Xaml::Controls::Primitives;  
  11. using namespace Windows::UI::Xaml::Interop;  
  12. using namespace Windows::UI::Xaml::Navigation;  
  13. using namespace Windows::UI::Xaml::Media;  
  14. using namespace Windows::Media;  
  15. using namespace Windows::Storage;  
  16.   
  17. struct App :ApplicationT<App>  
  18. {  
  19. public:  
  20.     virtual ~App() = default;  
  21.     static TextBlock CreateTextBlock(hstring);  
  22.     static void OnLaunched(LaunchActivatedEventArgs const&);  
  23.     static Thickness CreateThickness(int bottom, int left, int right, int top);  
  24. };  
  25. Thickness App::CreateThickness(int bottom, int left, int right, int top)  
  26. {  
  27.     Thickness think;  
  28.     think.Bottom = bottom;  
  29.     think.Left = left;  
  30.     think.Right = right;  
  31.     think.Top = top;  
  32.     return think;  
  33. }  
  34. TextBlock App::CreateTextBlock(hstring textCaption)  
  35. {  
  36.     TextBlock text;  
  37.     text.Text(textCaption);  
  38.     text.TextAlignment(TextAlignment::Center);  
  39.     text.Margin(CreateThickness(10, 10, 0, 10));  
  40.     return text;  
  41. }  
  42.   
  43. void App::OnLaunched(LaunchActivatedEventArgs const&)  
  44. {  
  45.       
  46.     auto txtTop = CreateTextBlock(L"AlignTopWithPanel");  
  47.     txtTop.Margin(CreateThickness(0, 10, 0, 0));  
  48.     auto txtBottom = CreateTextBlock(L"AlignBottomWithPanel");  
  49.     txtBottom.Margin(CreateThickness(0, 10, 0, 0));  
  50.     auto txtLeft = CreateTextBlock(L"AlignLeftWithPanel");  
  51.     txtLeft.Margin(CreateThickness(10, 0, 5, 50));  
  52.     auto txtRight = CreateTextBlock(L"AlignRightWithPanel");  
  53.   
  54.     auto txtHorCenter = CreateTextBlock(L"AlignHorizontalCenterWithPanel");  
  55.     auto txtVertical = CreateTextBlock(L"AlignVerticalCenterWithPanel");  
  56.     auto txtRightOf = CreateTextBlock(L"RightOfControl");  
  57.     txtRightOf.Foreground(SolidColorBrush(Colors::Red()));  
  58.   
  59.     auto txtLeftOf = CreateTextBlock(L"LeftOfControl");  
  60.     txtLeftOf.Foreground(SolidColorBrush(Colors::Blue()));  
  61.   
  62.     auto txtAbove = CreateTextBlock(L"AboveOfControl");  
  63.     txtAbove.Foreground(SolidColorBrush(Colors::Blue()));  
  64.       
  65.     auto txtBelow = CreateTextBlock(L"BelowOfControl");  
  66.     txtBelow.Foreground(SolidColorBrush(Colors::Green()));  
  67.   
  68.     auto txtHeader = CreateTextBlock(L"Modern C++/WinRT");  
  69.     txtHeader.Foreground(SolidColorBrush(Colors::Red()));  
  70.     txtHeader.HorizontalAlignment(HorizontalAlignment::Center);  
  71.     txtHeader.VerticalAlignment(VerticalAlignment::Center);  
  72.     txtHeader.Margin(CreateThickness(0, 10, 5, 100));  
  73.     txtHeader.FontSize(25);  
  74.       
  75.     RelativePanel RPanel;  
  76.     RPanel.Children().Append(txtTop);  
  77.     RPanel.Children().Append(txtBottom);  
  78.     RPanel.Children().Append(txtLeft);  
  79.     RPanel.Children().Append(txtRight);  
  80.     RPanel.Children().Append(txtHorCenter);  
  81.     RPanel.Children().Append(txtVertical);  
  82.     RPanel.Children().Append(txtRightOf);  
  83.     RPanel.Children().Append(txtLeftOf);  
  84.     RPanel.Children().Append(txtAbove);  
  85.     RPanel.Children().Append(txtBelow);  
  86.     RPanel.Children().Append(txtHeader);  
  87.   
  88.   
  89.     RPanel.SetAlignTopWithPanel(txtTop,true);  
  90.     RPanel.SetAlignBottomWithPanel(txtBottom, true);  
  91.     RPanel.SetAlignLeftWithPanel(txtLeft, true);  
  92.     RPanel.SetAlignRightWithPanel(txtRight, true);  
  93.   
  94.     RPanel.SetAlignVerticalCenterWithPanel(txtVertical, true);  
  95.     RPanel.SetAlignHorizontalCenterWithPanel(txtHorCenter,true);  
  96.     RPanel.SetRightOf(txtRightOf, PropertyValue::CreateInspectable(txtHorCenter));  
  97.     RPanel.SetLeftOf(txtLeftOf, PropertyValue::CreateInspectable(txtHorCenter));  
  98.     RPanel.SetAbove(txtAbove, PropertyValue::CreateInspectable(txtVertical));  
  99.     RPanel.SetBelow(txtBelow, PropertyValue::CreateInspectable(txtVertical));  
  100.   
  101.     RPanel.SetRightOf(txtHeader, PropertyValue::CreateInspectable(txtVertical));  
  102.       
  103.     RPanel.Margin(CreateThickness(10, 10, 10, 10));  
  104.     RPanel.BorderThickness(CreateThickness(1, 1, 1, 1));  
  105.     RPanel.BorderBrush(SolidColorBrush(Colors::Blue()));  
  106.   
  107.     Window window = Window::Current();  
  108.     window.Content(RPanel);  
  109.     window.Activate();  
  110. }  
  111. int __stdcall wWinMain(HINSTANCEHINSTANCEPWSTRint)  
  112. {  
  113.     Application::Start([](auto &&) {make<App>(); });  
  114.     return 0;  

 Output 

 
 
All the C++/WinRT samples' code is give here.

Conclusion

I hope you understood how to use the RelativePanel control.