Binding to indexers
In WPF, you can bind to 'property indexers'.
Example of a viewmodel that contains a Dictionary:
In the view I can now bind directly to items in this dictionary:
Is there any way I can do this in NoesisGUI as well? Binding to indexers doesn't seem to work, so at this moment I have to create a new property for each item in the dictionary. That is very cumbersome.
I want to use this to make an app that will support many languages. So instead of coding all the text in the XAML, I want to store the text in a Dictionary and I'm looking for a nice way to access these Dictionaries from XAML.
Example of a viewmodel that contains a Dictionary:
Code: Select all
public class ViewModel
{
public ViewModel()
{
Resources = new Dictionary<string, string>();
Resources["ButtonResource"] = "PLAY";
}
public Dictionary<string, string> Resources { get; private set; }
}
Code: Select all
<Button Content="{Binding Resources[ButtonResource]}"/>
I want to use this to make an app that will support many languages. So instead of coding all the text in the XAML, I want to store the text in a Dictionary and I'm looking for a nice way to access these Dictionaries from XAML.
-
sfernandez
Site Admin
- Posts: 3154
- Joined:
Re: Binding to indexers
We don't support the use of a .NET Dictionary as a ViewModel property.
An alternative to the dictionary would be using a Noesis Collection:
And you can use collection indexers in the xaml:
An alternative to the dictionary would be using a Noesis Collection:
Code: Select all
[Noesis.Extended]
public class ViewModel : Noesis.BaseComponent
{
public Noesis.Collection Texts { get; private set; }
public ViewModel()
{
Texts = new Noesis.Collection();
Texts.Add("One");
Texts.Add("Two");
Texts.Add("Three");
Texts.Add("Four");
}
}
public class _Test : MonoBehaviour
{
void Start()
{
var gui = GetComponent<NoesisGUIPanel>();
var root = gui.GetRoot<Noesis.Grid>();
root.SetDataContext(ViewModel());
}
}
Code: Select all
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Background="White">
<TextBlock Text="{Binding Texts[0]}"/>
<TextBlock Text="{Binding Texts[1]}"/>
<TextBlock Text="{Binding Texts[2]}"/>
<TextBlock Text="{Binding Texts[3]}"/>
</StackPanel>
</Grid>
Re: Binding to indexers
Thanks for the reply.
I won't be able to use the workaround that you propose. The key of the collection should really be a string and not just an integer. Using integers, the risk is too high that when the order changes the whole GUI becomes messed up.
I won't be able to use the workaround that you propose. The key of the collection should really be a string and not just an integer. Using integers, the risk is too high that when the order changes the whole GUI becomes messed up.
-
sfernandez
Site Admin
- Posts: 3154
- Joined:
Re: Binding to indexers
I understand the maintainability problems you exposed when using a Collection and integer indexers
The solution then is to use a ResourceDictionary of strings (I should probably think of this first ):
Then you can load that dictionary into a ViewModel property:
And then, bind to these string resources using the dictionary keys as indexers:
The solution then is to use a ResourceDictionary of strings (I should probably think of this first ):
Code: Select all
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:String x:Key="PlayButton">Play</sys:String>
<sys:String x:Key="SettingsButton">Settings</sys:String>
<sys:String x:Key="ExitButton">Exit</sys:String>
</ResourceDictionary>
Code: Select all
[Extended]
class ViewModel : BaseComponent
{
public ResourceDictionary Texts { get; private set; }
public ViewModel()
{
Texts = NoesisGUISystem.LoadXaml<ResourceDictionary>(
"Assets/UI/TextResources.xaml");
}
}
Code: Select all
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Margin="5" Content="{Binding Texts[PlayButton]}"/>
<Button Margin="5" Content="{Binding Texts[SettingsButton]}"/>
<Button Margin="5" Content="{Binding Texts[ExitButton]}"/>
</StackPanel>
</Grid>
Re: Binding to indexers
Thanks for this solution.
It works great in the Unity-editor, however I could not get it to work on Android. The call to NoesisGUISystem.LoadXaml() crashes, probably because on Android the assets are stored inside the APK file.
When I want to load assets at runtime, I usually store them in the 'StreamingAssets' folder and access them through the WWW class (this supports reading in the APK file). However, NoesisGUISystem.LoadXaml() just accepts a file-path so I cannot use this trick. It would be great if it accepted a WWW instance (or a string with the XAML-content).
Or is there another way to get this to work on Android?
It works great in the Unity-editor, however I could not get it to work on Android. The call to NoesisGUISystem.LoadXaml() crashes, probably because on Android the assets are stored inside the APK file.
When I want to load assets at runtime, I usually store them in the 'StreamingAssets' folder and access them through the WWW class (this supports reading in the APK file). However, NoesisGUISystem.LoadXaml() just accepts a file-path so I cannot use this trick. It would be great if it accepted a WWW instance (or a string with the XAML-content).
Or is there another way to get this to work on Android?
-
sfernandez
Site Admin
- Posts: 3154
- Joined:
Re: Binding to indexers
Which kind of crash are you getting? Can you provide any log error message, callstack, or dump?It works great in the Unity-editor, however I could not get it to work on Android. The call to NoesisGUISystem.LoadXaml() crashes, probably because on Android the assets are stored inside the APK file.
Our AssetPostProcessor does exactly that, it builds all the xaml files inside Assets folder and stores a binary representation in the StreamingAssets folder. In Android we are able to access the assets inside the .apk by using the AssetManager class. In fact, our SampleGallery demo is loading 3 ResourceDictionary xaml files when ControlGalleryLogic script is started.When I want to load assets at runtime, I usually store them in the 'StreamingAssets' folder and access them through the WWW class (this supports reading in the APK file). However, NoesisGUISystem.LoadXaml() just accepts a file-path so I cannot use this trick. It would be great if it accepted a WWW instance (or a string with the XAML-content).
Maybe you forgot to activate the Android platform in our Build Settings panel (menu Window -> NoesisGUI -> Settings). Or maybe your xaml has parsing errors and cannot be built. Have you checked the Unity Editor Console window? You can go to the NoesisGUI Settings panel, click the Build button to rebuild all the assets in the project, and take a look at the Console to see if anything is wrong.
Who is online
Users browsing this forum: maherne and 1 guest