Search code examples
datatemplateresourcedictionarywinui-3

How do I bind Resource Properties in a datatemplate?


I want to create an app for a game and decided I'd use winui3 for it as it seems to be the closest looking for what I've been searching for. So I'm quite new to this sort of stuff. Now to my Question: I've created a class that is supposed to represent a Job. It holds a basic "JobName", JobDescription and JobImage variable.

public class JobClass
{
    public string JobName = "null";
    public string JobDescription = "null"
    public byte[] JobImage = new byte[0];
}

Deriving from this class I've created several child classes that defines those variables.

public class BuilderClass : JobClass
{
    public BuilderClass()
    {
        JobName = Properties.Resources.Builder.JobName;
        JobDescription = Properties.Resources.Builder.JobDescription;
        JobImage = Properties.Resources.Builder.JobImage;
    }
}

I've then created a data template to be able to make them appear in a list

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DataTemplate
        x:Key="JobProfileTemplate">
        <StackPanel
            Orientation="Horizontal"
            Margin="2,0,0,0"
            BorderBrush="Black"
            BorderThickness="2">
            <Image
                Source="{Binding JobImage}"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"/>
            <TextBlock
                Text="{Binding JobTitle}"
                Margin="24,0,0,0"
                VerticalAlignment="Center"/>
        </StackPanel>
    </DataTemplate>
</ResourceDictionary>

On my page, I'm displaying the items like that

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ListView
            ItemsSource="{x:Bind JobsRepo}"
            ItemTemplate="{StaticResource JobProfileTemplate}"/>
    </Grid>

While the items are being added (since I can see the border I've created for debugging this). The string and the image are nowhere to be seen. enter image description here

I also get these path errors in my output console:

Error: BindingExpression path error: 'JobImage' property not found on 'Calendarium.Classes.Jobs.Builder'. BindingExpression: Path='JobImage' DataItem='Calendarium.Classes.Jobs.Builder'; target element is 'Microsoft.UI.Xaml.Controls.Image' (Name='null'); target property is 'Source' (type 'ImageSource')
Error: BindingExpression path error: 'JobName' property not found on 'Calendarium.Classes.Jobs.Builder'. BindingExpression: Path='JobName' DataItem='Calendarium.Classes.Jobs.Builder'; target element is 'Microsoft.UI.Xaml.Controls.TextBlock' (Name='null'); target property is 'Text' (type 'String')

I've tried following along with the DataTemplate documentation but don't really see a difference other than my properties being resource properties. I'm wondering if I can't bring them just like that?


Solution

  • You are getting those errors because Binding needs properties. So your JobClass needs to be something like this:

    public class JobClass
    {
        public string JobName { get; set; } = "null";
        public string JobDescription { get; set; } = "null"
        public byte[] JobImage { get; set; } = new byte[0];
    }
    

    The next is not directly related to your question but consider using x:Bind when you can. There's a good explanation here.

    So in your case:

    <Grid>
        <Grid.Resources>
            <DataTemplate
                x:Key="JobProfileTemplate"
                x:DataType="local:JobClass">
                <StackPanel
                    Margin="2,0,0,0"
                    BorderBrush="Black"
                    BorderThickness="2"
                    Orientation="Horizontal">
                    <Image
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Source="{x:Bind Image, Mode=OneWay}" />
                    <TextBlock
                        Margin="24,0,0,0"
                        VerticalAlignment="Center"
                        Text="{x:Bind Name, Mode=OneWay}" />
                </StackPanel>
            </DataTemplate>
        </Grid.Resources>
        <ListView
            ItemTemplate="{StaticResource JobProfileTemplate}"
            ItemsSource="{x:Bind JobsRepo, Mode=OneWay}" />
    </Grid>