Page 1 of 1

Editable resource dictionaries

Posted: 24 May 2018, 12:35
by Gwynneth
Hey, I'm working on a system which lets users create their own color schemes to be used by the UI. However, apparently editing a ResourceDictionary is not yet implemented in Noesis: the Add and Remove methods as well as iterating the ResourceDictionary (ICollection, IDictionary and IEnumerable) are currently missing. Would it be possible to add this functionality or is there some other way in which ResourceDictionaries can be edited?

Secondly, part of the color scheme system needs to load XAML files. Currently I've created two ways in which to load XAML files (and then turn them into ResourceDictionaries).

The first method loads the NoesisXAML assets created by NoesisGUI:
NoesisXaml redScheme = (NoesisXaml)Resources.Load("ColorSchemes/Red", typeof(NoesisXaml));
The second method loads in a text file. Currently, I'm loading a text file from Unity's Resources folder for testing but the same method should work for files on disk:

NoesisXaml redScheme = ScriptableObject.CreateInstance<NoesisXaml>();
redScheme.content = Encoding.ASCII.GetBytes(Resources.Load<TextAsset>("ColorSchemes/Red").text);
redScheme.source = "Assets/Resources/ColorSchemes/Red";

I would expect both of these NoesisXaml instances to be the same, but they aren't. The differences are small and both NoesisXaml's produce seemingly working ResourceDictionaries. However, is there a reason why they are different and perhaps not work in certain situations? The differences are:
  • Most importantly: the content property differs: the NoesisXaml asset contains three more bytes: 239 187 191.
  • When loading a NoesisXaml asset the NoesisXaml is already _registered whereas manually loading only sets _registered to true after .Load() has been called.
  • The properties fonts, texturePaths, textures and xamls are initialized when loading a NoesisXaml asset (most likely does not matter).
Lastly, although optional, I'd like to save a custom ResourceDictionary to a xaml file. Saving the NoesisXaml.content property to a file works. However, since the goal is to edit the ResourceDictionary the NoesisXaml instance will not contain the changes made by the user. Therefore, is there a way to convert the ResourceDictionary to a valid XAML string?

Kind regards,
Gwynn

Re: Editable resource dictionaries

Posted: 05 Jun 2018, 21:10
by sfernandez
I see that ResourceDictionary C# interface does not include the IDictionary methods, that's something we have to fix.
Could you please create a ticket in our bugtracker and we will include them in a following release.

Without that the only way to add/remove items right now in the dictionary is by using the RegisterName/UnregisterName methods.

Re: Editable resource dictionaries

Posted: 05 Jun 2018, 21:18
by sfernandez
Lastly, although optional, I'd like to save a custom ResourceDictionary to a xaml file. Saving the NoesisXaml.content property to a file works. However, since the goal is to edit the ResourceDictionary the NoesisXaml instance will not contain the changes made by the user. Therefore, is there a way to convert the ResourceDictionary to a valid XAML string?
There is no way now in Noesis to output a UI element or dictionary to disk. WPF offers a XamlWriter to achieve that:
https://stackoverflow.com/questions/104 ... ry-to-disk

Could you add it to our bugtracker?, if there are some requests about this feature we can think of implementing it.

Re: Editable resource dictionaries

Posted: 05 Jun 2018, 22:12
by jsantos
Most importantly: the content property differs: the NoesisXaml asset contains three more bytes: 239 187 191.
I don't know if this could be related to UTF8 encoding. Are these extra bytes appearing at the end? This is the way we are loading the content (you have the code in NoesisPostprocessor.cs) from FileStream:
xaml.content = new byte[file.Length];
file.Read(xaml.content, 0, (int)file.Length);
When loading a NoesisXaml asset the NoesisXaml is already _registered whereas manually loading only sets _registered to true after .Load() has been called.
Yes, you can ignore this difference. It makes sense, because you have to invoke .Load() soon or later.
The properties fonts, texturePaths, textures and xamls are initialized when loading a NoesisXaml asset (most likely does not matter).
Yes, in case you fill the content manually you are also in charge of setting the dependencies.

Apart from that, the two paths are exactly the same and should produce the same runtime objects.