Search code examples
c#xamlwinui-3winui

How to add converter in codebehind


How do you programatically in code behind use a converter on the display member path or use a itemtemplate with the converter?

     var listView = new ListView
         {
             ItemsSource = SomeObject,
             HorizontalAlignment = HorizontalAlignment.Right,
             SelectionMode=ListViewSelectionMode.Single,
             DisplayMemberPath=<---use converter here
         };
         var stackPanel = new StackPanel();
         stackPanel.Children.Add(listView);

Equivalent xaml example for reference:

    <ListView ItemsSource="{x:Bind Object, Mode=OneWay}">
                  <ListView.ItemTemplate>
                      <DataTemplate>
                          <TextBlock Text="{Binding Converter={StaticResource Converter}}"/>
                      </DataTemplate>
                  </ListView.ItemTemplate>
                </ListView>

Solution

  • You can create an ItemTemplate in code-behind using the XamlReader. This should be the closest thing to your XAML.

    string xamlString =
        """
        <DataTemplate
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="using:WinUIDemoApp">
            <Grid>
                <Grid.Resources>
                    <local:Converter x:Key="Converter" />
                </Grid.Resources>
                <TextBlock Text="{Binding Name, Converter={StaticResource Converter}}" />
            </Grid>
        </DataTemplate>
        """;
    
    var listView = new ListView();
    listView.ItemTemplate = XamlReader.Load(xamlString) as DataTemplate;
    

    Just make sure to replace using:WinUIDemoApp with the correct namespace for your converter.

    If you want to dynamically set the converter's namespace, you can:

    string converterNamespace = typeof(Converter).Namespace;
    string xamlString =
    $$$"""
    <DataTemplate
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:{{{converterNamespace}}}">
        <Grid>
            <Grid.Resources>
                <local:Converter x:Key="Converter" />
            </Grid.Resources>
            <TextBlock Text="{Binding Name, Converter={StaticResource Converter}}" />
        </Grid>
    </DataTemplate>
    """;
    

    and this is a known issue but you also need to explicitly declare? the converter in XAML so the converter gets registered as resources. One of the following to be specific:

    A. On your page

    <Page.Resources>
        <local:Converter x:Key="Converter" />
    </Page.Resources>
    

    B. On App.xaml

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
                <!--  Other merged dictionaries here  -->
            </ResourceDictionary.MergedDictionaries>
            <!--  Other app resources here  -->
            <local:Converter x:Key="Converter" />
        </ResourceDictionary>
    </Application.Resources>
    

    C. On a ResourceDictionary

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:WinUIDemoApp">
    
        <local:Converter x:Key="Converter" />
    
    </ResourceDictionary>