microsoft-ui-xaml icon indicating copy to clipboard operation
microsoft-ui-xaml copied to clipboard

x:DataType doesn't work with nested types from other assemblies

Open Sergio0694 opened this issue 5 years ago • 13 comments

Describe the bug

Using x:DataType doesn't work with nested types from other assemblies.

Consider the following viewmodel code:

public class RootViewModel
{
    public IEnumerable<object> Sections { get; } = new[] { new NestedViewModel() }; 

    public class NestedViewModel
    {
        public string SampleText => "Hello world";
    }
}

NOTE: this code must be placed in a separate project (eg. a .NET Standard 2.0 lib) to repro the issue. It works fine if the classes are right in the UWP app project.

And the following XAML code:

<Page
    x:Class="BindToNestedTypeRepro.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:libs="using:BindToNestedTypeReproLibs">
    <Page.DataContext>
        <libs:RootViewModel x:Name="ViewModel"/>
    </Page.DataContext>

    <Grid>
        <ListView ItemsSource="{x:Bind ViewModel.Sections}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:RootViewModel+NestedViewModel">
                    <TextBlock Text="{x:Bind SampleText}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

The app will fail to build and that data type for the template will not be recognized.

Steps to reproduce the bug

Steps to reproduce the behavior:

  1. Create a .NET Standard 2.0 project and add the viewmodel code
  2. Create a new blank UWP app and reference the other project
  3. Paste that XAML code above in MainPage
  4. Try to build and run

Expected behavior The app should run normally and XAML should recognize the data type and see the properties in the model.

Screenshots

image

Version Info

NuGet package version: n/a

Windows app type:

UWP Win32
Yes
Windows 10 version Saw the problem?
Insider Build (xxxxx)
May 2020 Update (19041) Yes
November 2019 Update (18363)
May 2019 Update (18362)
October 2018 Update (17763)
April 2018 Update (17134)
Fall Creators Update (16299)
Creators Update (15063)
Device form factor Saw the problem?
Desktop Yes
Xbox
Surface Hub
IoT

Sergio0694 avatar Sep 03 '20 20:09 Sergio0694

As pointed out by reflectronic, this can be accomplished by replacing x:DataType="local:RootViewModel.NestedViewModel" with x:DataType="local:RootViewModel+NestedViewModel". The above sample works when this is done. Hopefully there is a place in the docs where this can be mentioned explicitly.

BreeceW avatar Sep 04 '20 00:09 BreeceW

While the '+' syntax works, the VS XAML editor currently lacks proper support for it: It keeps complaining that the type "local:RootViewModel+NestedViewModel" does not exist: image

And as a consequence of that, x:Bind also does not list any of the public APIs of the NestedViewModel class in VS (meaning they have to be typed manually and any errors here (such as typos) will only be discovered during compilation).

Felix-Dev avatar Sep 04 '20 11:09 Felix-Dev

Oh that explains it! I had in fact tried to use + already, but assumed it wasn't supported when I saw VS showing those errors. I'm glad to hear the feature itself is technically working instead, and that it's mostly an issue with the tooling in VS 😄

~~Should I open this as a feedback in the VS feedback hub and close this issue?~~

EDIT: nevermind, I actually tried this again and I just can't get my app to build at all now. If I CTRL + click on the nested viewmodel type in XAML I can navigate correctly to the target type, but then I still get a whole lot of XAML compiler error when trying to run the app. I get the following:

XamlCompiler error WMC0909: Cannot resolve DataType subPages:SettingsSubPageViewModel+IdeSettingsSectionViewModel

This happens even with just an empty DataTemplate just declaring x:DataType as a test.

@Felix-Dev can you actually run your app fine with that setup? What SDK are you targeting? 🤔

EDIT 2: tried by targeting both 18362 and 19041, both individually and for both target and minimum, same error.

EDIT 3: working in a repro project with just this code, but failing to build in my app. Investigating...

Sergio0694 avatar Sep 04 '20 12:09 Sergio0694

Alright I figured out what is causing the issue 🚀

@BreeceW Looks like the XAML compiler fails whenever the target type is defined in a separate assembly. In my case, I have a separate .NET Standard 2.0 project with all my viewmodels, and with that even the x:DataType="ns:Root+Nested" syntax fails.

You should be able to repro this locally by just creating a .NET Standard 2.0 project and moving the test viewmodel there. I assume this should work and it's just a bug in the XAML compiler that causes the type lookup to fail?

Also, would you be able to suggest any possible workarounds for now (other than just moving the types to the app project)? Thanks! 😊

Sergio0694 avatar Sep 04 '20 15:09 Sergio0694

@Sergio0694 Sorry, just saw your ping now.

Yes, if I move the class to a separate assembly, I cannot compile any longer as well (previously, I had both the XAML and the ViewModel class in the same assembly).

Felix-Dev avatar Sep 04 '20 15:09 Felix-Dev

Yet another reason why it was and still is a TERRIBLE idea to not be able to programmatically create DataTemplates. XAML is not a programming language.

Please tell me why I'm wrong.

baskren avatar Nov 05 '21 15:11 baskren

Yes, using XAML is clearly a terrible idea because of this one bug. For the same reason, using C# is also a terrible idea because one time I found a bug in the C# compiler.

This is not the right place to have this conversation, and that comment is completely off topic. There is a separate proposal to create data templates in C#, I'd recommend subscribing there if you're interested 🙂

Sergio0694 avatar Nov 05 '21 16:11 Sergio0694

Thanks Sergio for being a good sport. Sorry ... I guess I just needed to vent a bit.

baskren avatar Nov 05 '21 16:11 baskren

Bumping this (see https://github.com/microsoft/microsoft-ui-xaml/discussions/8638).

Sergio0694 avatar Jul 13 '23 21:07 Sergio0694

Still now working in .NET 8

TonyLugg avatar Mar 15 '24 19:03 TonyLugg

Still now working in .NET 8

I also have this issue in my WinUI project

hippieZhou avatar Mar 22 '24 13:03 hippieZhou

~I just confirmed that the + syntax works on Microsoft.WindowsAppSDK v1.6.241114003 even though VS throws some errors.~ Stopped working and does not run now. The test project that worked before is deleted and not sure why the new test project is not working. 🤔

AndrewKeepCoding avatar Dec 11 '24 04:12 AndrewKeepCoding

Just create a class that inherits from NestedViewModel:

public class MyNestedViewModel : RootViewModel.NestedViewModel {}

I am getting warning and it bindings to properties aren't working at all:

Microsoft.Maui.Controls.Xaml.Diagnostics.BindingDiagnostics: Warning: Mismatch between the specified x:DataType (MyNestedViewModel ) and the current binding context (RootViewModel+NestedViewMode).

sinatrocious avatar Oct 06 '25 08:10 sinatrocious

@sinatrocious You are right. That doesn't work and I removed my earlier comment. It looks like we need to wait until this is properly addressed.😅

If you absolutely need a temporary hack, check out this repo.

It uses a custom MSBuild task that edits the generated .g.cs files and replaces code like RootViewModel+NestedViewMode with RootViewModel.NestedViewMode.

I was just experimenting to see if it worked. While it seems that it does, I don't recommend it. Custom MSBuild tasks seems to have some file locking issue that I couldn't workaround.

AndrewKeepCoding avatar Oct 07 '25 08:10 AndrewKeepCoding

@AndrewKeepCoding, I moved nested class BluetoothManager.Device out and renamed it to BluetoothDevice. That's not too bad. But by doing so I've lost some nice feature of nested class being able to access private members of its parent class and had to make certain members of manager public (not nice).

I hope this will be fixed one day. Despite A+B syntax works at run-time I can't stand so many errors and warnings during compile-time.

sinatrocious avatar Oct 08 '25 09:10 sinatrocious