- KeldorKatarn
- Posts: 193
- Joined:
Noesis erroneously reports dublicate element name
I have an issue here with Noesis reporting a duplicate element name where there is none. I'm not sure what causes this but I had this happen before after a XAML was being reloaded.
The specified name only exists once (I only have two XAML files right now so this is pretty easy to confirm)
I had it happen once before but now I cannot get rid of it.
I get this:
This MIGHT be caused by be creating DataTemplates for my viewmodels in the code. However IF that's the case this is a bug.
I'm not sure this is the cause, however if I place the View UserControl inside the other one directly,
instead of using a ContentControl bound to the VM using the View as a generated DataTemplate,
then it doesn't report this error.
Apparently Noesis thinks the name is declared twice by A) the name being in the View used in the datatemplate and B) the view simply existing as an asset. The latter shouldn't matter.
Again I'm not sure that this is the cause. (The name btw is just the name of a parent container DockPanel, so nothing inside another template or anything)
As a reminder, this is what that code does:
The specified name only exists once (I only have two XAML files right now so this is pretty easy to confirm)
I had it happen once before but now I cannot get rid of it.
I get this:
Code: Select all
[Error] [noesis] Cannot register duplicate name 'IgnoreMe' in this namescope.
NoesisUnity.UnityLog() at /NoesisGUI/Plugins/NoesisUnity.cs:148
146: case LogLevel.Error:
147: {
-->148: Debug.LogError("[noesis] " + message);
149: break;
150: }
FrameworkElement.MeasureOverride() at /NoesisGUI/Plugins/API/Proxies/FrameworkElementExtend.cs:45
43: if (_measureBaseCallback != null)
44: {
-->45: _measureBaseCallback(swigCPtr, ref availableSize, ref desiredSize);
46: }
47: return desiredSize;
FrameworkElement.CallMeasureOverride() at /NoesisGUI/Plugins/API/Proxies/FrameworkElementExtend.cs:89
87: {
88: _measureBaseCallback = callback;
-->89: Size desiredSize = MeasureOverride(availableSize);
90: _measureBaseCallback = null;
Extend.FrameworkElementMeasure() at /NoesisGUI/Plugins/API/Core/Extend.cs:1964
1962: if (element != null)
1963: {
-->1964: desiredSize = element.CallMeasureOverride(availableSize, callback);
1965: if (desiredSize.IsEmpty) desiredSize = new Size(0, 0);
1966: }
View.SetSize() at /NoesisGUI/Plugins/API/Core/View.cs:57
55: public void SetSize(int width, int height)
56: {
-->57: Noesis_View_SetSize(CPtr, width, height);
58: }
NoesisView.UpdateSize() at /NoesisGUI/Plugins/NoesisView.cs:857
855: if (_camera != null)
856: {
-->857: _uiView.SetSize(_camera.pixelWidth, _camera.pixelHeight);
858: }
859: else if (_texture != null)
NoesisView.ExternalUpdateInternal() at /NoesisGUI/Plugins/NoesisView.cs:900
898: }
899: #endif
-->900: UpdateSize();
901: UpdateInputs();
902: NoesisUnity.IME.Update(_uiView);
NoesisView.LateUpdate() at /NoesisGUI/Plugins/NoesisView.cs:875
873: if (!_enableExternalUpdate)
874: {
-->875: ExternalUpdateInternal();
876: }
877: }
I'm not sure this is the cause, however if I place the View UserControl inside the other one directly,
instead of using a ContentControl bound to the VM using the View as a generated DataTemplate,
then it doesn't report this error.
Apparently Noesis thinks the name is declared twice by A) the name being in the View used in the datatemplate and B) the view simply existing as an asset. The latter shouldn't matter.
Again I'm not sure that this is the cause. (The name btw is just the name of a parent container DockPanel, so nothing inside another template or anything)
As a reminder, this is what that code does:
Code: Select all
var pairs = this.viewModelTypes.Select(
vmType => new { ViewModelType = vmType, ViewType = GetViewType(vmType) });
var root = NoesisView.Content;
foreach (var pair in pairs.Where(pair => pair.ViewModelType != typeof(ShellViewModel)))
{
DataTemplateManager.RegisterDataTemplate(pair.ViewModelType, pair.ViewType, root.Resources);
}
Code: Select all
public static void RegisterDataTemplate(Type viewModelType, Type viewType, ResourceDictionary dictionary)
{
var dataTemplate = CreateTemplate(viewModelType, viewType);
#if NOESIS
dictionary.Add(viewModelType, dataTemplate);
#else
dictionary.Add(dataTemplate.DataTemplateKey, dataTemplate);
#endif
}
Code: Select all
private static DataTemplate CreateTemplate(Type viewModelType, Type viewType)
{
string xamlTemplate;
if (viewType != null)
{
xamlTemplate = "<DataTemplate\n" +
" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n" +
" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n" +
$" xmlns:vm=\"clr-namespace:{viewModelType.Namespace};assembly={viewModelType.Assembly.GetName().Name}\"\n" +
$" xmlns:v=\"clr-namespace:{viewType.Namespace};assembly={viewType.Assembly.GetName().Name}\"\n" +
$" DataType=\"{{x:Type vm:{viewModelType.Name}}}\">\n" +
$" <v:{viewType.Name} />\n" + "</DataTemplate>";
}
else
{
xamlTemplate = "<DataTemplate\n" +
" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n" +
" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n" +
$" xmlns:vm=\"clr-namespace:{viewModelType.Namespace};assembly={viewModelType.Assembly.GetName().Name}\"\n" +
$" DataType=\"{{x:Type vm:{viewModelType.Name}}}\">\n" +
" <Border Background=\"Magenta\">\n" +
$" <TextBlock Margin=\"5\" Foreground=\"White\" FontWeight=\"Bold\" Text=\"Cannot find view for {viewModelType.FullName}.\" />\n" +
" </Border>\n</DataTemplate>";
}
var template = (DataTemplate)XamlReader.Parse(xamlTemplate);
return template;
}
- KeldorKatarn
- Posts: 193
- Joined:
Re: Noesis erroneously reports dublicate element name
I keep having this problem unfortunately. Everytime I give something a name, NOESIS keeps reporting it as duplicated.
Also for a while now, every time I open Unity, my project complains about XAMLs being missing, until I manually reimport them. Something is going on here. I'd appreciate some help finding out what the issue is here.
Also for a while now, every time I open Unity, my project complains about XAMLs being missing, until I manually reimport them. Something is going on here. I'd appreciate some help finding out what the issue is here.
Re: Noesis erroneously reports dublicate element name
Is this happening since you enabled Hot-reloading in our settings panel?I keep having this problem unfortunately. Everytime I give something a name, NOESIS keeps reporting it as duplicated.
Does it happen everytime your close Unity and open it again?Also for a while now, every time I open Unity, my project complains about XAMLs being missing, until I manually reimport them. Something is going on here. I'd appreciate some help finding out what the issue is here.
- KeldorKatarn
- Posts: 193
- Joined:
Re: Noesis erroneously reports dublicate element name
Hot reloading does not seem to be the issue no.
I just upgraded to Unity 2020.3.6f1 and this still happens. So I don't think Unity is to blame.
And yes everytime I open the Editor now and then try to play my scene, I get the error and need to manually reimport my XAML views.
I even deleted my entire Library folder and let Unity reimport everything but that didn't fix it. If I quit and reopen the editor and press play, I get this:
Something about this dynamic generation of datatemplates with Views inside causes an issue here apparently. Both with the naming and with finding the xamls.
I just upgraded to Unity 2020.3.6f1 and this still happens. So I don't think Unity is to blame.
And yes everytime I open the Editor now and then try to play my scene, I get the error and need to manually reimport my XAML views.
I even deleted my entire Library folder and let Unity reimport everything but that didn't fix it. If I quit and reopen the editor and press play, I get this:
Code: Select all
[Error] [noesis] <memory>(7): Xaml not found 'Assets/Scripts/MapEditor/Views/DialogView.xaml'
GUI.LoadComponent() at /NoesisGUI/Plugins/API/Core/NoesisGUI.cs:292
290: public static void LoadComponent(object component, string filename)
291: {
-->292: Noesis_LoadComponent(Extend.GetInstanceHandle(component), filename);
293: }
DialogView.InitializeComponent() at /Scripts/MapEditor/Views/DialogView.xaml.cs:37
35: private void InitializeComponent()
36: {
-->37: GUI.LoadComponent(this, "Assets/Scripts/MapEditor/Views/DialogView.xaml");
38: }
39: #endif
VacuumBreather.Montreal.MapEditor.Views.DialogView..ctor() at /Scripts/MapEditor/Views/DialogView.xaml.cs:27
25: public DialogView()
26: {
-->27: InitializeComponent();
28: }
Extend.CreateInstance() at /NoesisGUI/Plugins/API/Core/Extend.cs:4697
4695: info.Type.FullName));
4696: }
-->4697: object instance = info.Creator();
4699: if (isBaseComponent)
GUI.ParseXaml() at /NoesisGUI/Plugins/API/Core/NoesisGUI.cs:261
259: public static object ParseXaml(string xamlText)
260: {
-->261: IntPtr root = Noesis_ParseXaml(xamlText);
262: return Extend.GetProxy(root, true);
263: }
XamlReader.Parse() at /NoesisGUI/Plugins/API/Proxies/XamlReader.cs:20
18: public static class XamlReader {
19: public static object Parse(string xamlText) {
-->20: return Noesis.GUI.ParseXaml(xamlText);
21: }
DataTemplateManager.CreateTemplate() at /Scripts/UI/DataTemplateManager.cs:71
69: }
-->71: var template = (DataTemplate)XamlReader.Parse(xamlTemplate);
73: return template;
DataTemplateManager.RegisterDataTemplate() at /Scripts/UI/DataTemplateManager.cs:32
30: public static void RegisterDataTemplate(Type viewModelType, Type viewType, ResourceDictionary dictionary)
31: {
-->32: var dataTemplate = CreateTemplate(viewModelType, viewType);
34: #if NOESIS
UserInterfaceInstaller.Start() at /Scripts/MapEditor/Installers/UserInterfaceInstaller.cs:64
62: foreach (var pair in pairs.Where(pair => pair.ViewModelType != typeof(ShellViewModel)))
63: {
-->64: DataTemplateManager.RegisterDataTemplate(pair.ViewModelType, pair.ViewType, root.Resources);
65: }
- KeldorKatarn
- Posts: 193
- Joined:
Re: Noesis erroneously reports dublicate element name
Is it maybe because right now I'm putting the datatemplates into the Resources of root control instead of the Application resources (which I only will be able to access in the next version)? Is that causing this issue?
I'm putting them into NoesisView.Content.Resources now. Is that an issue?
I'm putting them into NoesisView.Content.Resources now. Is that an issue?
-
sfernandez
Site Admin
- Posts: 2991
- Joined:
Re: Noesis erroneously reports dublicate element name
Hi, another question to try reproducing this. The named element is the UserControl of the view itself, right? something like
Or does this happen with any named element inside the view?
Code: Select all
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Views.SomeView"
x:Name="IgnoreMe">...
- KeldorKatarn
- Posts: 193
- Joined:
Re: Noesis erroneously reports dublicate element name
No it's not the UserControl. The first time it happened the named element was a DockPanel. Right now it's a TreeView in a File Dialog I made. I need to name that since I want to attach an event hander in code behind.
Re: Noesis erroneously reports dublicate element name
As the rest of assets in Unity, if you want to load a XAML by code you need to put them in a Resources folder (we don't recommend this) or have references to them from your scene. For this you can use our <noesis:Xaml.Dependencies> or just store each .asset you need in a property of a Unity component.And yes everytime I open the Editor now and then try to play my scene, I get the error and need to manually reimport my XAML views.
It is working for you when you reimport everything because at reimport time we load each xaml and unity keeps them in memory for a while.
We know this is confusing, and the root of the problem is having a LoadXaml using string in Unity. We are considering removing this in the future. What do you think?
- KeldorKatarn
- Posts: 193
- Joined:
Re: Noesis erroneously reports dublicate element name
Ah gotcha. I can do that. I should be able to put them into my bootstrapper component.
As for XamlReader taking a string, please keep that. I'm using that to generate placeholder datatemplates like Caliburn. So if a view isn't found, I'm generating a DataTemplate with a magenta background and atextblock saying "View not found for ViewModel XYZ". That way you can work with just your viewmodels and run the application without it crashing. You just get placeholders everywhere where you haven't created the View yet. That is a great workflow with Caliburn.Micro and I'd like to be able to replicate that in Unity.
Ok. I changed it so I reference every NoesisXaml (had to look up what type those assets actually are). That fixes the missing Xaml problem.
However the double name issue remains.
As for XamlReader taking a string, please keep that. I'm using that to generate placeholder datatemplates like Caliburn. So if a view isn't found, I'm generating a DataTemplate with a magenta background and atextblock saying "View not found for ViewModel XYZ". That way you can work with just your viewmodels and run the application without it crashing. You just get placeholders everywhere where you haven't created the View yet. That is a great workflow with Caliburn.Micro and I'd like to be able to replicate that in Unity.
Ok. I changed it so I reference every NoesisXaml (had to look up what type those assets actually are). That fixes the missing Xaml problem.
However the double name issue remains.
-
sfernandez
Site Admin
- Posts: 2991
- Joined:
Re: Noesis erroneously reports dublicate element name
Hi, found the source of the problem with the duplicate names. It is a bug (#1994) in the parser when the xaml being loaded has a template in its root.
We will fix it for the next release.
In the meantime you can wrap the DataTemplate in a ResourceDictionary and define it as a resource:
We will fix it for the next release.
In the meantime you can wrap the DataTemplate in a ResourceDictionary and define it as a resource:
Code: Select all
xamlTemplate = "<ResourceDictionary\n"+
" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n" +
" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n" +
$" xmlns:vm=\"clr-namespace:{viewModelType.Namespace};assembly={viewModelType.Assembly.GetName().Name}\"\n" +
$" xmlns:v=\"clr-namespace:{viewType.Namespace};assembly={viewType.Assembly.GetName().Name}\">\n" +
" <DataTemplate x:Key=\"t\"\n" +
$" DataType=\"{{x:Type vm:{viewModelType.Name}}}\">\n" +
$" <v:{viewType.Name} />\n" +
" </DataTemplate>" +
"</ResourceDictionary>";
Code: Select all
var dict = (ResourceDictionary)XamlReader.Parse(xamlTemplate);
return (DataTemplate)dict["t"];
Who is online
Users browsing this forum: Google [Bot], Semrush [Bot] and 23 guests