Search code examples
c#xamlbindingwinui-3windows-community-toolkit

How to bind MetadataControl items to a collection in XAML with WINUI 3


I'm trying to use the MetadataControl from the windows community toolkit.

In the sample app, items are added programmatically and I can't find a way to bind to a class with a data template directly in Xaml.

I tried the following code but it won't work:

<controls:MetadataControl Items="{x:Bind myClass}">
    <ControlTemplate>
         <DataTemplate x:DataType="local:myClass">
            <.....>
         </DataTemplate>
     </ControlTemplate>
</controls:MetadataControl>

If anybody had a example of how to do bind it directly in XAML without having to populate items from code, it will we great.

Thank you


Solution

  • MetadataItem is a struct and AFAIK you can't initialize a struct in XAML.

    I also recommend that you create a collection of MetadataItems like it in the samples.

    That said, I build up this code using an Attached Property and achieved what you are trying to do. The namings are verbose but I think I'd be easier to get what it represents in this case. I hope this helps.

    MetadataControlExtension.cs

    using CommunityToolkit.WinUI.UI.Controls;
    using Microsoft.UI.Xaml;
    using System.Collections.Generic;
    
    namespace MetadataControlExtension;
    
    public class MetadataControlExtensionItem
    {
        public string Label { get; set; } = string.Empty;
    }
    
    public class MetadataControlExtensionItemList : List<MetadataControlExtensionItem>
    {
    }
    
    public class MetadataControlExtension : DependencyObject
    {
        public static IEnumerable<MetadataControlExtensionItem> GetItemsSource(DependencyObject obj)
        {
            return (IEnumerable<MetadataControlExtensionItem>)obj.GetValue(ItemsSourceProperty);
        }
    
        public static void SetItemsSource(DependencyObject obj, IEnumerable<MetadataControlExtensionItem> value)
        {
            obj.SetValue(ItemsSourceProperty, value);
        }
    
        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.RegisterAttached(
                "ItemsSource",
                typeof(IEnumerable<MetadataControlExtensionItem>),
                typeof(MetadataControlExtension), new PropertyMetadata(0, OnItemsSourcePropertyChanged));
    
        private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is MetadataControl metadataControl && e.NewValue is IEnumerable<MetadataControlExtensionItem> itemsSource)
            {
                List<MetadataItem> metadataItems = new();
    
                foreach (MetadataControlExtensionItem item in itemsSource)
                {
                    metadataItems.Add(new MetadataItem() { Label = item.Label });
                }
    
                metadataControl.Items = metadataItems;
            }
        }
    }
    

    MainWindow.xaml

    <Window
        x:Class="MetadataControlTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls"
        xmlns:ex="using:MetadataControlExtension"
        mc:Ignorable="d">
    
        <Grid>
            <controls:MetadataControl>
                <ex:MetadataControlExtension.ItemsSource>
                    <ex:MetadataControlExtensionItemList>
                        <ex:MetadataControlExtensionItem Label="1st Item"/>
                        <ex:MetadataControlExtensionItem Label="2nd Item"/>
                        <ex:MetadataControlExtensionItem Label="3rd Item"/>
                        <ex:MetadataControlExtensionItem Label="4th Item"/>
                        <ex:MetadataControlExtensionItem Label="5th Item"/>
                    </ex:MetadataControlExtensionItemList>
                </ex:MetadataControlExtension.ItemsSource>
            </controls:MetadataControl>
        </Grid>
    
    </Window>