Need help on XAML syntax for ThemeResource and binding in DataTemplate

杨岑 171 Reputation points
2024-04-16T10:06:26.62+00:00

I have the following code and XAML:

class FileCategory
    {
        public string Code { get; set; }
        public string Name { get; set; }
    }
<!-- <Page.Resources> section contains theme resources -->

<ComboBox.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal">
            <Image Source="{ThemeResource ResourceKey={Binding Path=Code}}"
                   Width="20" Height="20"/>
            <Rectangle Width="5" Height="0"/>
            <TextBlock Text="{Binding Path=Name}"/>
        </StackPanel>
    </DataTemplate>
</ComboBox.ItemTemplate>

But during runtime, I got unhandled exception when I click on the ComboBox list:

Failed to assign to property 'Windows.UI.Xaml.ThemeResource.ResourceKey'

I believe the syntax for the Image element is not correct. What is the correct syntax?

Universal Windows Platform (UWP)
{count} votes

1 answer

Sort by: Most helpful
  1. Junjie Zhu - MSFT 18,476 Reputation points Microsoft Vendor
    2024-04-18T10:20:54.0966667+00:00

    Hi @杨岑 ,

    Welcome to Microsoft Q&A!

    I want to bind its Source to a ThemeResource identified by FileCategory.Code.

    Sorry, there is no way to do this in UWP. If you need to modify this source dynamically, it is recommended to modify the Source in the FrameworkElement.ActualThemeChanged Event like in this thread.

    Here's my test code, I hope it helps.

     public sealed partial class MainPage : Page
     {
         ObservableCollection<FileCategory> Categories = new ObservableCollection<FileCategory>
         {
             new FileCategory { Name = "aaa", Description = "aaa item", imgPath="Assets/Images/light-0.png" },
             new FileCategory { Name = "bbb", Description = "bbb item", imgPath="Assets/Images/light-1.png" },
             new FileCategory { Name = "ccc", Description = "ccc item", imgPath="Assets/Images/light-2.png" },
         };
         public MainPage()
         {
             this.InitializeComponent();
             
         }
         private void Page_Loaded(object sender, RoutedEventArgs e)
         {
             Page page = (Page)sender;
             if (page.ActualTheme == ElementTheme.Light)
             {
                 for (int i = 0; i < Categories.Count; i++)
                 {
                     Categories[i].imgPath = "Assets/Images/light-" + i.ToString() + ".png";
                 } 
             }
             else if (page.ActualTheme == ElementTheme.Dark)
             {
                 for (int i = 0; i < Categories.Count; i++)
                 {
                     Categories[i].imgPath = "Assets/Images/dark-" + i.ToString() + ".png";
                 }
             }
         }
         private void Page_ActualThemeChanged(FrameworkElement sender, object args)
         {
             if (sender.ActualTheme == ElementTheme.Light)
             {
                 for (int i = 0; i < Categories.Count; i++)
                 {
                     Categories[i].imgPath = "Assets/Images/light-" + i.ToString() + ".png";
                 }
             }
             else if (sender.ActualTheme == ElementTheme.Dark)
             {
                 for (int i = 0; i < Categories.Count; i++)
                 {
                     Categories[i].imgPath = "Assets/Images/dark-" + i.ToString() + ".png";
                 }
             }
         }
     }
     //public class FileCategory
     //{
     //    public string Name { get; set; }
     //    public string Description { get; set; }
     //    public string imgPath { get; set; }
     //}
     public class FileCategory : INotifyPropertyChanged
     {
         private string _name;
         private string _description;
         private string _imgPath;
         public string Name
         {
             get { return _name; }
             set
             {
                 _name = value;
                 OnPropertyChanged("Name");
             }
         }
         public string Description
         {
             get { return _description; }
             set
             {
                 _description = value;
                 OnPropertyChanged("Description");
             }
         }
         public string imgPath 
         {
             get { return _imgPath; }
             set
             {
                 _imgPath = value;
                 OnPropertyChanged("imgPath");
             }
         }
         public event PropertyChangedEventHandler PropertyChanged;
         protected void OnPropertyChanged([CallerMemberName] string name = null)
         {
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
         }
     }
    
    <Page
        x:Class="collectionComboboxTest.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:collectionComboboxTest"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
        ActualThemeChanged="Page_ActualThemeChanged"
        Loaded="Page_Loaded"
        >
        <Grid>
            <StackPanel Orientation="Horizontal">
                <ComboBox x:Name="combo1"
        ItemsSource="{x:Bind Categories, Mode=TwoWay}"
        DisplayMemberPath="Name"/>
                <ComboBox x:Name="fileTypeListBox"
              ItemsSource="{x:Bind Categories, Mode=OneWay}"
              SelectedValuePath="Name">
                    <ComboBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <Image Source="{Binding imgPath}"
                       Width="20" Height="20"/>
                                <TextBlock Text="{Binding Path=Name}"/>
                            </StackPanel>
                        </DataTemplate>
                    </ComboBox.ItemTemplate>
                </ComboBox>
            
            </StackPanel>
        </Grid>
    </Page>
    

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.