'DataTemplate doesn't work when moved to ResourceDictionary
I was trying to move a DataTemplate from a ListView into a resource dictionary and it somehow broke the Bindings, I believe.
I verified that when I hardcode the Textblock text it displays in the listview and it seems the listview datasource binding is working, it just can't display my data.
Here's the Dictionary:
<ResourceDictionary
x:Class="Marathon.Resources.ListViewTemplate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Marathon">
<DataTemplate x:Key="LVTemplate" x:DataType="local:Result">
<StackPanel Orientation="Horizontal" Height="Auto" Padding="12" AutomationProperties.Name="{x:Bind ID}">
<TextBlock Text="{x:Bind ToString()}" VerticalAlignment="Center" Style="{ThemeResource BaseTextBlockStyle}" Foreground="White" Margin="12,0,0,0" FontSize="24"/>
</StackPanel>
</DataTemplate>
</ResourceDictionary>
Here's how I'm referencing the template:
<ListView Grid.Row="1" ItemsSource="{x:Bind VM.Results}" ItemTemplate="{StaticResource LVTemplate}" Background="#FF343434" >
</ListView>
And Here's what it looks like when I have it inside the listview template instead of the dictionary:
<ListView Grid.Row="1" ItemsSource="{x:Bind VM.Results}" Background="#FF343434" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Result">
<StackPanel Orientation="Horizontal" Height="Auto" Padding="12" AutomationProperties.Name="{x:Bind ID}">
<TextBlock Text="{x:Bind ToString()}" VerticalAlignment="Center" Style="{ThemeResource BaseTextBlockStyle}" Foreground="White" Margin="12,0,0,0" FontSize="24"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here's screenshots of it working when not in the ResourceDictionary:
And here's it not working:
Edit: Here's my App.xaml:
<Application
x:Class="Marathon.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Marathon">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/VCenterTextBox.xaml"/>
<ResourceDictionary Source="Resources/KeypadButton.xaml"/>
<ResourceDictionary Source="Resources/ListViewTemplate.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Solution 1:[1]
When using x:Bind
inside a ResourceDictionary
, you'll need to declare the dictionary partial
and create a code-behind file to instantiate it:
<ResourceDictionary
x:Class="Marathon.Resources.ListViewTemplate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Marathon">
<DataTemplate x:Key="LVTemplate" x:DataType="local:Result">
<StackPanel Orientation="Horizontal" Height="Auto" Padding="12" AutomationProperties.Name="{x:Bind ID}">
<TextBlock Text="{x:Bind ToString()}" VerticalAlignment="Center" Style="{ThemeResource BaseTextBlockStyle}" Foreground="White" Margin="12,0,0,0" FontSize="24"/>
</StackPanel>
</DataTemplate>
</ResourceDictionary>
Code-behind: using Windows.UI.Xaml.Data;
namespace Marathon.Resources
{
public partial class ListViewTemplate
{
public ListViewTemplate()
{
InitializeComponent();
}
}
}
App.xaml:
Hint: It is important to instantiate the template like an object, so that the partial class's constructor and the "InitializeComponent()" gets invoked. The point is that x:Bind
is not resolved by the XAML engine at runtime, but by the compiler. That's what makes x:Bind
more efficient.
To reference the resource, don't merge the file. Create an instance of the partial class (to trigger the compiler).
<Application
x:Class="Marathon.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Marathon">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:ListViewTemplate />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Solution 2:[2]
The best way is to add reference in you App.xaml then you can use your DataTemplate everywhere in your app.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Path/To/Your/ResourceFile/ListViewDataTemplate.xaml" />
<ResourceDictionary Source="Another/Path/To/Your/ResourceFile/EGButtonTemplateStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Michal Kania |