Search Unity

Feature Request Why isn't TemplateContainer flex-grow 1 by default ?

Discussion in 'UIElements' started by aybe, Jan 16, 2019.

  1. aybe

    aybe

    Joined:
    May 24, 2015
    Posts:
    104
    Not sure if it's intended but say you add a ListView to a window, you will wonder for a long time why it's not shown ! It's simply because the root container does not fill the window by default ... it would make sense it does by default.
     
  2. aybe

    aybe

    Joined:
    May 24, 2015
    Posts:
    104
    Additionally, I believe that ListView should get the same treatment. (unless specified in the docs ofc)
     
  3. etienne_phil_unity

    etienne_phil_unity

    Unity Technologies

    Joined:
    Jan 15, 2019
    Posts:
    15
    Hello! trying with 2018.3.1f1, on my end, the rootVisualContainer fills the parent window by default, however, if we add a ListView, it does not fill its parent and I also think this is problematic, checking this with the team, thanks for your feedback!
     
  4. aybe

    aybe

    Joined:
    May 24, 2015
    Posts:
    104
    Great !

    Forgot to mention: I'm using 2019.1.0a13
     
  5. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    421
    ListView will not expand on its own. It needs an explicit size (or set to automatically flex). It cannot determine its size from its contents because the whole point is for it to be a different size than its content (usually smaller), and then only display and manage the few elements that are visible.
     
  6. aybe

    aybe

    Joined:
    May 24, 2015
    Posts:
    104
    Okay that makes sense !!!
     
  7. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,400
    What is the TemplateContainer for? How do I access it?

    It's currently getting in the way of me making something stretch to the height of the window.
     
  8. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    421
    Cloning a VisualTreeAsset (using CloanTree()) creates a TemplateContainer (which is a VisualElement) that contains as children all the elements in the UXML asset. You need a parent element because the UXML can have multiple elements at its root.

    But you can style this TemplateContainer any way you want after you cloned it, just like any other VisualElement.

    Alternatively, you can use VisualTreeAsset.CloneTree(VisualElement target) to clone the contents of a UXML asset directly into an existing VisualElement (like the rootVisualElement).
     
  9. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,400
    Thanks, I get it now. I had copied code from the example and didn't really get what it was doing with root.Add(uxmlVE). The unnamed uxmlVE was the TemplateContainer. Now I have it stretching full height.

    Is it possible to clone a tree without it creating a template? I don't like the idea of it auto-creating things. We can already add a root/container in the UXML.

    I had code like this, so it seemed redundant:
    Code (csharp):
    1. var root = this.GetRootVisualContainer();
    2.  
    3. var visualTree = Resources.Load("XML/index") as VisualTreeAsset;
    4. var uxmlVE = visualTree.CloneTree(null);
    5. uxmlVE.AddStyleSheetPath("CSS/styles");
    6.  
    7. root.Add(uxmlVE);
    8.  
    So the hierarchy ended up with:
    Code (csharp):
    1. #root (GetRootVisualContainer)
    2.     TemplateContainer
    3.         #AnotherRoot (in the UXML)
    4.             #MainContentWrapper
    5.                 #ColumnL
    6.                 #ColumnR
    So I had to delete the #AnotherRoot from the UXML because of the auto-created one... but at least it is working now!
     
  10. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    421
    See my previous comment: :)

     
  11. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,400
    I don't seem to have that overload in this version of Unity, unfortunately. It also asks for slotInsertionPoints...
     
  12. aybe

    aybe

    Joined:
    May 24, 2015
    Posts:
    104
    @uDamian

    Good to know, just got rid of that extra level!

    @Stardog

    Usage with 2019.1.0a13 in OnEnable:

    Code (CSharp):
    1. var xml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
    2.     "Assets/XXX.uxml");
    3. var css = AssetDatabase.LoadAssetAtPath<StyleSheet>(
    4.     "Assets/XXX.uss");
    5.  
    6. xml.CloneTree(rootVisualElement);
    7.  
    8. var tree = rootVisualElement;
    9.  
    10. tree.styleSheets.Add(css);
    2019-01-18_22-02-56.png

    Now use 'tree' to configure your stuff, I did introduce a variable because it's shorter/simpler/clearer to type 'tree' than 'rootVisualElement' when referring to it.
     
  13. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    421
    You can just pass `null` for the other arguments. :)
     
  14. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,400
    I tried null after it, but it returns void at that point, so I can't get a reference and have to query instead. It might be because I'm on 2018.3.0f2 and .NET 3.5.

    The code @aybe posted won't compile. I'll try to update at some point.

    Meanwhile, I just did this, and moved AddStyleSheetPath onto the root, and it works ok:
    Code (csharp):
    1. var tree = Resources.Load("XML/index") as VisualTreeAsset;
    2. tree.CloneTree(root, null);
    Capture.PNG
     
    Last edited: Jan 18, 2019
  15. Rocktavious

    Rocktavious

    Joined:
    May 10, 2017
    Posts:
    41
  16. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    421
    Yes, you have to query for specific elements after you clone. But you have to do that for both versions of CloneTree(). It's just that one creates a new element (TemplateContainer) and the other simply puts the contents under an existing element.