microsoft-ui-xaml
microsoft-ui-xaml copied to clipboard
Can't specify `x:DataType` of DataTemplate in ResourceDictionary
Describe the bug
I have a templated control that has a property of type Windows.Foundation.Collections.IObservableVector<Int32> Items{ get; }; that's bound to a ListView.ItemsSource and I can't specify the x:DataType in the DataTemplate. It gives
Themes\Generic.xaml(12,43): XamlCompiler error WMC0612: The XAML Binary Format (XBF) generator reported syntax error '0x09C4' : Property Not Found
Steps to reproduce the bug
- Create a new C++WinUI3 project
- Create a new templated control with this idl, write a dummy code-behind
[bindable]
[default_interface]
runtimeclass MyControl : Microsoft.UI.Xaml.Controls.Control
{
MyControl();
Windows.Foundation.Collections.IObservableVector<Int32> Items{ get; };
}
- In
Themes/Generc.xaml, add this style
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:_28_CannotUseInt32AsDataType">
<Style TargetType="local:MyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyControl">
<ListView ItemsSource="{Binding Items, RelativeSource={RelativeSource Mode=TemplatedParent}}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="x:Int32"/>
</ListView.ItemTemplate>
</ListView>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Expected behavior
Builds fine
Screenshots
No response
NuGet package version
WinUI 3 - Windows App SDK 1.7.1: 1.7.250401001
Windows version
Windows 11 (24H2): Build 26100
Additional context
I think this issue is rather about having an empty DataTemplate tag. This error also occurred when using any other data type; if the DataTemplate tag is empty (either immediately closed or not having any children), the XAML compiler returns an XBF error. @HO-COOH can you confirm the issue does not occur if you have content within the datatemplate?
@marcelwgn Nope. Even if I put random content in DataTemplate gives me same error.
<DataTemplate x:DataType="x:Int32">
<TextBlock Text="Me"/>
</DataTemplate>
UPDATE: The issue seems to be that I cannot specify any x:DataType in a resource dictionary that does not have a code-behind. And this is quite ridiculous, since this is the files created by adding a templated control.
x:Bind relies on code-generation and needs a backing file to generate in. I'm doing this extensively in one of our libraries. Example: https://github.com/Esri/arcgis-maps-sdk-dotnet-toolkit/tree/main/src/Toolkit/Toolkit.WinUI/UI/Controls/BookmarksView
x:Bind relies on code-generation and needs a backing file to generate in. I'm doing this extensively in one of our libraries. Example: https://github.com/Esri/arcgis-maps-sdk-dotnet-toolkit/tree/main/src/Toolkit/Toolkit.WinUI/UI/Controls/BookmarksView
x:Bind relies on code-behind, yes, but I didn't found x:DataType relies on code-behind documented anywhere. I can use it without x:Bind, something like this
<DataTemplate x:DataType="x:String>
<TextBlock Text="{Binding}"/>
</DataTemplate>
update your resource control to this and it will run.
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
x:Class="_28_CannotUseInt32AsDataType.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:_28_CannotUseInt32AsDataType">
<Style TargetType="local:MyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyControl">
<ListView ItemsSource="{Binding Items, RelativeSource={RelativeSource Mode=TemplatedParent}}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="x:Int32">
<TextBlock Text="{Binding}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Needed to add an x:class and content inside the datatemplate. Both are required. If after changing it can't find the class, close and reopen the solution then retry.
@HO-COOH Why are you setting the datatype if you aren't going to be using x:bind? That sort of defeats the purpose. It exists for the purpose of x:bind.
@Skittles2519 Thanks, this solves my issue. What if the resource dictionary contains multiple templates for templated control? Like the default visual studio file template created a Theme/Generic.xaml, which seems to suggest it "should" contain multiple control templates.
@HO-COOH thats fine: they are all in the same resource dictionary class
@dotMorten So I can conclude that the default generated Theme/Generic.xaml (when I add a new Templated Control) should contain x:Class for the first templated control I added?
x:class goes in the first xml tag (the ResourceDictionary one, not in the individual styles).
x:class goes in the first xml tag (the
ResourceDictionaryone, not in the individual styles).
Yes I know that already. I mean currently, when I add a new templated control for the first time, the Generic.xaml looks like this
But it should really add a x:Class, like this:
<ResourceDictionary
x:Class="winui3cpp.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:winui3cpp">
<Style TargetType="local:MyControl" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyControl">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Yes except don't use the MyControl class - use a class for the resources in general. Here's what I do:
<ResourceDictionary
x:Class="winui3cpp.ThemeResources"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:winui3cpp">
<Style TargetType="local:MyControl" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyControl">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
And then also add the partial C# file:
namespace winui3cpp;
internal sealed partial class ThemeResources : ResourceDictionary
{
public ThemeResources()
{
InitializeComponent();
}
}
You can also add methods in here to do method binding to which is useful instead of using converters.