KeldorKatarn
Topic Author
Posts: 193
Joined: 30 May 2014, 10:26

DataTemplate creation in code

07 Apr 2021, 14:24

Hey guys, somehow whenever I try to take another shot at NoesisGUI I seem to keep doing things that are just beyond the limits of possibility.
Since I've completely given up on getting a MVVM Framework like Caliburn to run on Noesis since there's still API missing and Caliburn has other issues with it's static IoC,
I decided to do my own little framework. However I immediately ran into problems again, and one is related to the issues I had with caliburn. Parsing XAML.
But there's also another question that needs solving.

So I'm trying to use Views as DataTemplates so I can just databind a ContentControl to a ViewModel and the View is shown because it's the DataTemplate for that ViewModel type.
So far so good, that's a standard technique.
However I wanted to go a step further and didn't want to declare those DataTemplates one by one in some ResourceDictionary.

Instead I wanted to just look through all public types that match being a view and just create those DataTemplates dynamically.
I found a good code snipped online and got that to work in WPF, but unfortunately not in Noesis:

    #region Using Directives

    using System;
#if NOESIS
    using Noesis;
#else
    using System.Windows;
    using System.Windows.Markup;
#endif

    #endregion

    public static class DataTemplateManager
    {
        #region Public Methods

        public static void RegisterDataTemplate<TViewModel, TView>(ResourceDictionary dictionary)
            where TView : FrameworkElement
        {
            RegisterDataTemplate(typeof(TViewModel), typeof(TView), dictionary);
        }

        public static void RegisterDataTemplate(Type viewModelType, Type viewType, ResourceDictionary dictionary)
        {
            DataTemplate template = CreateTemplate(viewModelType, viewType);
            var key = template.DataTemplateKey;
            
            dictionary.Add(key, template);
        }

        #endregion

        #region Private Methods

        private static DataTemplate CreateTemplate(Type viewModelType, Type viewType)
        {
            const string XamlTemplate = "<DataTemplate DataType=\"{{x:Type vm:{0}}}\"><v:{1} /></DataTemplate>";
            var xaml = string.Format(
                XamlTemplate,
                viewModelType.Name,
                viewType.Name);

            var context = new ParserContext();

            context.XamlTypeMapper = new XamlTypeMapper(new string[0]);
            context.XamlTypeMapper.AddMappingProcessingInstruction(
                "vm",
                viewModelType.Namespace,
                viewModelType.Assembly.FullName);
            context.XamlTypeMapper.AddMappingProcessingInstruction(
                "v",
                viewType.Namespace,
                viewType.Assembly.FullName);

            context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
            context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
            context.XmlnsDictionary.Add("vm", "vm");
            context.XmlnsDictionary.Add("v", "v");

            var template = (DataTemplate)XamlReader.Parse(xaml, context);

            return template;
        }

        #endregion
    }
So first of all, ParserContext doesn't exist. So I'm missing that one. I am also missing XamlTypeMapper.
The DataTemplate type is missing the DataTemplateKey property, so I cannot add it to the dictionary.

And finally... what dictionary am I even adding this to?
In WPF I'm using Application.Current.Resources. What should I use in Unity for Noesis?
Is there a global dictionary or a NoesisView specific dictionary I can use to dynamically add resources?

I'm assuming for now I'm out of luck?
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: DataTemplate creation in code

09 Apr 2021, 12:05

Hi, the WPF framework is huge and we are implementing more and more things on each version based usually on the most requested features by our clients. If you find anything you need please don't hesitate to ask here in the forums and/or create a ticket in our bugtracker asking for it.
So first of all, ParserContext doesn't exist. So I'm missing that one. I am also missing XamlTypeMapper.
We support the basic version of XamlReader.Parse with just a string. In this case you have to provide the namespaces directly in the xaml:
string 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>";
The DataTemplate type is missing the DataTemplateKey property, so I cannot add it to the dictionary.
When no explicity string key is provided we use the DataType of the DataTemplate as key for the ResourceDictionary. We do the same for Styles where we use the TargetType as key.
In WPF I'm using Application.Current.Resources. What should I use in Unity for Noesis?
Is there a global dictionary or a NoesisView specific dictionary I can use to dynamically add resources?
We also have a global application resource dictionary but I just noticed there is no API in C# to obtain it. I created ticket #1962 to add it for next release.
 
KeldorKatarn
Topic Author
Posts: 193
Joined: 30 May 2014, 10:26

Re: DataTemplate creation in code

09 Apr 2021, 12:30

When no explicity string key is provided we use the DataType of the DataTemplate as key for the ResourceDictionary.
But why do I get an error in Unity then? Unity complains that I need to provide a key manually.
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: DataTemplate creation in code

09 Apr 2021, 13:13

Please see my answer to your other post: viewtopic.php?f=3&t=2256&p=12448#p12448
 
KeldorKatarn
Topic Author
Posts: 193
Joined: 30 May 2014, 10:26

Re: DataTemplate creation in code

10 Apr 2021, 18:02

We also have a global application resource dictionary but I just noticed there is no API in C# to obtain it. I created ticket #1962 to add it for next release.
Thank you, that'll be what I need to make this work. I'm still hoping to get a nice little MVVM framework going here.

The main issues with porting all of Caliburn.Micro are still it's handling of IoC with a static class, which just doesn't work well if you use the framework for multiple things at the same time,
and the action/message feature (which I honestly feel is a bit redundand and involved for a simple framework anyway.

I'll try to get some of the ViewModel base classes to work, to have an easy mechanic for the views to correspond in ContentControls to the viewmodels (by viewfinder and the automatic DataTemplate generation) and see whether that works. I will not add the EventAggregator since there's plenty stuff like that already in the Unity world, like in UniRx.
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: DataTemplate creation in code

14 Apr 2021, 11:05

Great, we will love to see that framework up and running with Noesis :)
 
User avatar
jsantos
Site Admin
Posts: 3905
Joined: 20 Jan 2012, 17:18
Contact:

Re: DataTemplate creation in code

14 Apr 2021, 12:37

I decided to do my own little framework. However I immediately ran into problems again, and one is related to the issues I had with caliburn. Parsing XAML.
But there's also another question that needs solving.
Our development is fully based on the feedback from our clients. It is true that we have many fronts, but please, insists on the missing things or issues you find. Make sure you create reports in the tracker for each issue separately (reports including many problems or being too generic are hard to close and have less priority). Don't worry about creating many tickets, that's better for us. And if possible, include a clear repro case. This increases the chances of solving it.

Thanks!

Who is online

Users browsing this forum: Google [Bot] and 61 guests