Lucian Bumb
Lucian Bumb

Reputation: 2881

Why binding TextBlock Text Property not working as expected

I have a DataTemplate which suppose to give me this kind of output:

Expected Template

when using this code:

    <DataTemplate x:DataType="data:MenuItem" x:Key="MenuItemTemplate">
        <StackPanel>
            <Viewbox Margin="10 10 10 2">
                <TextBlock FontFamily="Segoe MDL2 Assets" Text="{x:Bind Icon}" />
            </Viewbox>
            <TextBlock HorizontalAlignment="Center" Text="{x:Bind Name}" />
        </StackPanel>
    </DataTemplate>

but ... I get no Icon:

enter image description here

I think is something wrong in my binding, but I dont know what.

The menu item model is like this:

public class MenuItem
    {
        public MenuItem(string name, string icon)
        {
            Name = name;
            Icon = $"&#x{icon};";
        }

        public string Name { get; set; }
        public string Icon { get; set; }
    }

If I just provide the icon in plain text, like this:

       <DataTemplate x:DataType="data:MenuItem" x:Key="MenuItemTemplate">
            <StackPanel>
                <Viewbox Margin="10 10 10 2">
                    <TextBlock FontFamily="Segoe MDL2 Assets" Text="&#xE913;" />
                </Viewbox>
                <TextBlock HorizontalAlignment="Center" Text="{x:Bind Name}" />
            </StackPanel>
        </DataTemplate>

the icon is displayed correctly, but when using binding not.

Can you please help me understand what is wrong in my approach?

Edit : added full code example

public sealed partial class MainPage : Page
{
    private ObservableCollection<MenuItem> MenuItems;

    public MainPage()
    {
        this.InitializeComponent();
        MenuItems = new ObservableCollection<MenuItem>(new List<MenuItem>
        {
            new MenuItem("Home","E913"),
            new MenuItem("Volume","EC3F"),
            new MenuItem("Scrap","E74C"),
            new MenuItem("Report","ED25"),
        });
      
    }
}

public class MenuItem
{
    public MenuItem(string name, string icon)
    {
        Name = name;
        Icon = $"&#x{icon};";
    }

    public string Name { get; set; }
    public string Icon { get; set; }
}

and xalm code:

<Page.Resources>
        <DataTemplate x:DataType="data:MenuItem" x:Key="MenuItemTemplate">
            <StackPanel>
                <Viewbox Margin="10 10 10 2">
                    <TextBlock FontFamily="Segoe MDL2 Assets" Text="{x:Bind Icon}" />
                </Viewbox>
                <TextBlock HorizontalAlignment="Center" Text="{x:Bind Name}" />
            </StackPanel>
        </DataTemplate>
    </Page.Resources>

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="90" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <ListBox Grid.Column="0" ItemsSource="{x:Bind MenuItems}"
             ItemTemplate="{StaticResource MenuItemTemplate}" />

</Grid>

Upvotes: 2

Views: 264

Answers (2)

Peter Duniho
Peter Duniho

Reputation: 70652

Ah. On closer reflection, I see that you are trying to bind at runtime a value that needs to be interpreted at compile time.

Specifically, XAML is just a special-case of XML. When you use a string with a character entity like "&#xE913;", it is the XAML compiler that interprets the entity, as part of processing the XAML as XML. Of course, this is done before your program ever runs.

When you bind the same text at runtime, you are just binding a bunch of characters. They aren't interpreted in any special way. They are just displayed as the characters. Instead, you need to provide the actual value directly:

MenuItems = new ObservableCollection<MenuItem>(new List<MenuItem>
{
    new MenuItem("Home","\uE913"),
    new MenuItem("Volume","\uEC3F"),
    new MenuItem("Scrap","\uE74C"),
    new MenuItem("Report","\uED25"),
});

I.e. use the Unicode character escaping for a C# string literal to specify the character code point you want to use. And of course in the model, don't try to form the entity syntax; just use the text directly:

public class MenuItem
{
    public MenuItem(string name, string icon)
    {
        Name = name;
        Icon = icon;
    }

    public string Name { get; set; }
    public string Icon { get; set; }
}

Upvotes: 2

Pharaz Fadaei
Pharaz Fadaei

Reputation: 1827

Writing unicode code in this format &#xE913 is the way that can be used only in xaml to represent a unicode character. In C#, you need to write it this way \uE913 and you should do it where you add your menu items to the list. You can't and don't need to do the formatting like you did unless you use a converter which is simply overkill in this situation.

new MenuItem("Home","\uE913"),
new MenuItem("Volume","\uEC3F"),
new MenuItem("Scrap","\uE74C"),
new MenuItem("Report","\uED25"),

Upvotes: 1

Related Questions