User avatar
digimbyte
Topic Author
Posts: 37
Joined: 14 Nov 2017, 21:42

How to get Actual Size programmatically based on internal content?

06 Jun 2019, 05:51

I'm looking at dynamic menu's that can be clamped to within screen space
but I can't get the ActualHeight/Width to set the offsets.
I saw in an older thread that this depends on the UI being passed to the renderer first.
but it was never explained the process of doing such.

so I was wondering how I might be able to constrain the dimensions
based on internal content as ActualHeight returns 0?
        Button origin = ((Noesis.Button)sender);
        Point position = origin.PointToScreen(new Point(0f,26f));

        Noesis.StackPanel Menu = new Noesis.StackPanel
        {
            Background = Brushes.Beige,
            MinWidth = 150,
            MaxWidth = 250,
            MinHeight = 12,
            CanVerticallyScroll = true
        };

        for (int i = 0; i < Singularity.random(3, 15); i++)
        {
            Menu.Children.Add(new Button
            {
                Focusable = false,
                Content = Singularity.random(1, 200).ToString(),
                Margin = Thickness.Parse("1")
                //Padding = Thickness.Parse("15,5")
            });
        }
        Debug.Log("HEIGHT: " + Menu.ActualHeight);
        Debug.Log("WIDTH: " + Menu.ActualWidth);
        
        
        position.X = Mathf.Clamp(position.X, 0, Screen.width - Menu.ActualWidth);
        position.Y = Mathf.Clamp(position.Y, 0, Screen.height - Menu.ActualHeight);
 
User avatar
digimbyte
Topic Author
Posts: 37
Joined: 14 Nov 2017, 21:42

Re: How to get Actual Size programmatically based on internal content?

08 Jun 2019, 05:29

I've been working on a data structure to handle the buttons but still, no progress on clamping elements to the view
Image
I've moved code around so it should add to the uiRoot before calling ActualWidth
however, I need some sort of callback to the loaded event
this scopes outside what I'm familiar with in C#
 
User avatar
digimbyte
Topic Author
Posts: 37
Joined: 14 Nov 2017, 21:42

Re: How to get Actual Size programmatically based on internal content?

10 Jun 2019, 07:39

Found a solution, the documentation doesn't give an example.
once it's added to the main UI, you add a .Loaded =+(){}'
DropMenu.Loaded += (object _sender, Noesis.RoutedEventArgs e) =>
        {
            Button origin = ((Noesis.Button)originalSender);
            Point position = origin.PointToScreen(new Point(0f, 26f));
            position.Y = Mathf.Clamp(position.Y, 0, uiRoot.ActualHeight - DropMenu.ActualHeight);
            position.X = Mathf.Clamp(position.X, 0, uiRoot.ActualWidth - DropMenu.ActualWidth);
            DropMenu.Margin = Thickness.Parse(position.X.ToString() + "," + position.Y.ToString() + ",0,0");
        };
 
User avatar
sfernandez
Site Admin
Posts: 1550
Joined: 22 Dec 2011, 19:20

Re: How to get Actual Size programmatically based on internal content?

10 Jun 2019, 12:20

Hi, sorry for the late answer.

ActualWidth and ActualHeight properties are calculated during the layout process in the UI Update, so they won't provide meaningful values just after element gets created or its size/position properties has changed. You can force an update by calling element.UpdateLayout(), or as you have done, after creating the element wait until Loaded event is raised.

But in this situation, couldn't you use a simple StackPanel with HorizontalAlignment="Right" and let the system handle the positioning?

And just a suggestion, instead of creating Thickness objects parsing a string, you can construct them like:
DropMenu.Margin = new Thickness(position.X, position.Y, 0, 0);
 
User avatar
digimbyte
Topic Author
Posts: 37
Joined: 14 Nov 2017, 21:42

Re: How to get Actual Size programmatically based on internal content?

11 Jun 2019, 01:01

it actually uses stack panels already, but it's not a child of the initiator, as I am attempting to create menu's like you would in windows application where content needs to overlay other elements.
        Noesis.StackPanel DropMenu = new Noesis.StackPanel
        {
            Background = Brushes.Beige,
            MinWidth = 150,
            MaxWidth = 250,
            MinHeight = 12,
        };
        
        DropMenu.HorizontalAlignment = HorizontalAlignment.Left;
        DropMenu.VerticalAlignment = VerticalAlignment.Top;
        ActiveMenus.Add(DropMenu);
        uiRoot.Children.Add(DropMenu);
most of the information I was going with was based on my findings in the documentation and here in the forums.
it might be good to have both our codes added to the documentation as examples
 
User avatar
sfernandez
Site Admin
Posts: 1550
Joined: 22 Dec 2011, 19:20

Re: How to get Actual Size programmatically based on internal content?

11 Jun 2019, 14:04

I am attempting to create menu's like you would in windows application where content needs to overlay other elements.
There are specific controls for that in Noesis, you can define a Menu with MenuItem children to show a popup with options. And it can be dynamically filled by binding the ItemsSource of the Menu and MenuItems with the corresponding data:
<UserControl
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.Resources>
        <HierarchicalDataTemplate x:Key="SubItemTemplate" ItemsSource="{Binding MenuItems}">
            <TextBlock Text="{Binding DisplayName}" />
        </HierarchicalDataTemplate>
    </UserControl.Resources>
    <DockPanel>
        <Menu DockPanel.Dock="Top" ItemsSource="{Binding MenuItems}" ItemTemplate="{StaticResource SubItemTemplate}"/>
        <Grid />
    </DockPanel>
</UserControl>
class MenuItemVM
{
  public ObservableCollection<MenuItemVM> MenuItems { get; private set; }
  public string DisplayName { get; private set; }
  
  public MenuItemVM(string name)
  {
    MenuItems = new ObservableCollection<MenuItemVM>();
    DisplayName = name;
  }
}
Is that what you are trying to do?
 
User avatar
digimbyte
Topic Author
Posts: 37
Joined: 14 Nov 2017, 21:42

Re: How to get Actual Size programmatically based on internal content?

12 Jun 2019, 01:03

to an extent, yes. but due to the nature of my project, I can't rely on XAML files as the content needs to change dynamically. either through user customization or live updates
so I'm attempting to do all this mostly in C#

I want to break away from the rigidity of the XAML files and the problems they come with, ie using blend.
and create a middle software that can be fed data objects to generate the GUI on demand.
 
User avatar
sfernandez
Site Admin
Posts: 1550
Joined: 22 Dec 2011, 19:20

Re: How to get Actual Size programmatically based on internal content?

12 Jun 2019, 11:05

What I'm trying to say is that you can create a Menu control in code and feed it with a list of items and it will automatically populate and position the menu items for you. There is no need to manually create buttons and calculate positions, that is all already done by the layout system.

Everything that can be done in XAML can be written in code (or it should be, otherwise it is probably because of a bug or something missing in the API).

For example, following my previous code you can write this:
Menu menu = new Menu();
menu.ItemsSource = menuItemsList;
menu.ItemTemplate = (DataTemplate)XamlReader.Parse(
  "<HierarchicalDataTemplate ItemsSource=\"{Binding MenuItems}\">\n" +
  "  <TextBlock Text=\"{Binding DisplayName}\" />\n" +
  "</HierarchicalDataTemplate>");
DockPanel.SetDock(menu, Dock.Top);
DockPanel panel = new DockPanel();
panel.Children.Add(menu);
I want to break away from the rigidity of the XAML files and the problems they come with, ie using blend.
What problems did you find working with Blend? We would like to know if there is something we can improve for future versions.
 
User avatar
digimbyte
Topic Author
Posts: 37
Joined: 14 Nov 2017, 21:42

Re: How to get Actual Size programmatically based on internal content?

12 Jun 2019, 13:38

Originally, I was looking at menu items, but realized that some content I would need in those span outside typical menu entries, such as volume controls and other tools.
so I moved to StackPanels - I will look at menu's again.

as for Blend, it's an overbearing application with tools and widgets that seem convoluted and impractical when you want basic elements on demand.
combine that with the user interface that looks like a broken powerpoint, it doesn't have a smooth workflow or decent user experience.
it also broke several things when attempting to merge and use it with the Unity workflow.
in the end, it wasn't worth it. especially since Noesis supports runtime building, which is perfect.

Ideally, what I want is to be able to create GUI with nested .dot notation, not move vectors and rulers around. it is backwards to what I would want when creating a GUI.
hopefully, when I'm done, I would like to submit my script to the samples so others can look at doing it programmatically
 
User avatar
jsantos
Site Admin
Posts: 2490
Joined: 20 Jan 2012, 17:18
Contact:

Re: How to get Actual Size programmatically based on internal content?

14 Jun 2019, 14:15

hopefully, when I'm done, I would like to submit my script to the samples so others can look at doing it programmatically
That would be awesome!

Who is online

Users browsing this forum: No registered users and 3 guests