EisenbergEffect
Topic Author
Posts: 19
Joined: 22 Mar 2013, 15:09

Dynamic Xaml Instantiation

25 Mar 2013, 22:23

Consider the following Xaml:
<Border>
    <ContentControl x:Name="Placeholder" />
</Border>
A common scenario is that based on program logic, I need to instantiate different UIs and add set them as the Placeholder's Content. Is there a way to do this? I'm primarily working in Unity and didn't see an existing API. I thought that I might be able to use the UIRenderer class to perform the instantiation and then use the GetRoot API to pull out the control tree and set it on the ContentControl. I haven't tried this yet, but wanted to hear from you on a recommendation and/or any drawbacks to this.
 
User avatar
sfernandez
Site Admin
Posts: 3005
Joined: 22 Dec 2011, 19:20

Re: Dynamic Xaml Instantiation

25 Mar 2013, 22:59

Loading dynamically a XAML is a trivial task using C++ API. You just use the Resource System to load the XAML resource, and get the contents of the resource to assign them to the appropriate container:
#include <NsCore/NsSystem.h>
#include <NsResource/IResourceSystem.h>
#include <NsGui/IUIResource.h>
#include <NsGui/ContentControl.h>

using namespace Noesis;
using namespace Noesis::Resource;
using namespace Noesis::Gui;

void LoadXAML(ContentControl* container, const NsChar* xamlFile)
{
    const Ptr<IResourceSystem>& resourceSystem = NsGetSystem<IResourceSystem>();
    Ptr<IUIResource> xamlResource = NsDynamicCast<Ptr<IUIResource> >(resourceSystem->Load(xamlFile));
    container->SetContent(xamlResource->GetRoot());
}
The API that is currently available in Unity that deals with XAML files is a bit more complex (it creates and associates a GUI Renderer to the loaded content), but in our next beta release it will be possible to do exactly what you want to do ;)
 
bwheatley
Posts: 4
Joined: 09 Aug 2014, 06:42

Re: Dynamic Xaml Instantiation

16 Aug 2014, 10:51

Has this beta been released to allow this with Unity yet?
 
User avatar
sfernandez
Site Admin
Posts: 3005
Joined: 22 Dec 2011, 19:20

Re: Dynamic Xaml Instantiation

16 Aug 2014, 11:07

Sure, you can load XAML files in runtime by calling NoesisGUISystem.LoadXAML():

Assets/UI_XAML/TestOther.xaml
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Button x:Name="btn" Width="200" Height="100"/>
</Grid>
public class Test : MonoBehaviour
{
    void Start()
    {
        Noesis.Grid grid = NoesisGUISystem.LoadXAML<Noesis.Grid>("Assets/UI_XAML/TestOther.xaml");

        var gui = GetComponent<NoesisGUIPanel>();
        var root = gui.GetRoot<Noesis.Grid>();
        var container = roo.FindName<Noesis.ContentControl>("container");
        container.SetContent(grid);
    }
}
 
bwheatley
Posts: 4
Joined: 09 Aug 2014, 06:42

Re: Dynamic Xaml Instantiation

16 Aug 2014, 11:15

Oh cool thanks for the quick response. I've been loving Noesis and slowly converting everything from NGUI over. I'm just trying to figure out the best way to dynamically instantiate new elements in a xaml (like multiple image boxes).

But maybe there is a dynamic combo box i could potentially use instead of trying to manually instantiate new xaml elements.
 
User avatar
sfernandez
Site Admin
Posts: 3005
Joined: 22 Dec 2011, 19:20

Re: Dynamic Xaml Instantiation

16 Aug 2014, 11:43

If you are creating data at runtime that you want to be displayed in the UI, you better try to use Data Binding: viewtopic.php?f=3&t=75#p2388.

You create in Unity the classes that represent your Data. Then you can create your interface in Blend (or any editor you like) to design how to represent your data (using Bindings to the properties provided by the Data classes). Finally, when application is started, you set in the interface root the DataContext (the ViewModel that exposes the properties), and that's all.
 
User avatar
sfernandez
Site Admin
Posts: 3005
Joined: 22 Dec 2011, 19:20

Re: Dynamic Xaml Instantiation

16 Aug 2014, 11:44

Another sample of Data Binding: viewtopic.php?f=12&t=391
 
bwheatley
Posts: 4
Joined: 09 Aug 2014, 06:42

Re: Dynamic Xaml Instantiation

16 Aug 2014, 19:16

Thank you for the thoughtful and helpful answers! I'll check them out now.
Money well spent especially with getting help. :)
 
bwheatley
Posts: 4
Joined: 09 Aug 2014, 06:42

Re: Dynamic Xaml Instantiation

16 Aug 2014, 19:32

Thanks for pointing me in the right direction. Looks like I need to use databinding plus a <scrollviewer> to allow for horizental scrolling of inventory items.
Right now i worked off your databinding tutorial and i got it working with a dropdown.

I appreciate the help!
https://www.evernote.com/shard/s36/sh/7 ... 0985491f4c
 
wwizz
Posts: 3
Joined: 17 Aug 2014, 21:27

Re: Dynamic Xaml Instantiation

18 Aug 2014, 23:13

I have a follow-up question on this topic. I managed to dynamic load an xaml this way, however getting references of elements in the loaded xaml by name fails.

To clarify see the next files:

The container xaml
<UserControl 
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
	        xmlns:noesis="clr-namespace:NoesisGUIExtensions" >
    <Border x:Name="container"  />
    
</UserControl>

The loaded xaml
<UserControl 
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
			 xmlns:noesis="clr-namespace:NoesisGUIExtensions"
	         mc:Ignorable="d" 
             d:DesignHeight="400" d:DesignWidth="300">
	
    <Grid>
		<Border BorderThickness="2" Padding="10" >
			<Grid x:Name="mainGrid">
				
				<StackPanel x:Name="buttonPanel">
					<TextBlock>Title</TextBlock>
					<Button x:Name="Button1" Content="Button1" />
					<Button x:Name="Button2" Content="Button2" />
				</StackPanel>
			</Grid>
		</Border>
	</Grid>
</UserControl>

Then I use the following code to load a xaml
 
public void Start()
    {
        var loaded = NoesisGUISystem.LoadXaml<UserControl>("Assets/PressIt.GUI/Test1.xaml");
        gui = FindObjectOfType<NoesisGUIPanel>();
        var root = gui.GetRoot<FrameworkElement>();
        var container = root.FindName<Border>("container");
        
        container.SetChild(loaded);
        container.SetVisibility(Visibility.Visible);

        button1= container.FindName<Button>("Button1");
        button2 = container.FindName<Button>("Button2");

        button1.Click += OnButton1Click; //<=== NULL reference exception
        button2.Click += OnButton2Click;
    }
The button1 and button2 variables are null, meaning that the FindName<Button>("...") failed. Note that the xaml works perfectly if I load the xaml statically in NoesisGUIPanel.

Any ideas?

Who is online

Users browsing this forum: Bing [Bot] and 8 guests