Search code examples
c#xamluwpmvvm-light

Why is my MenuFlyoutItem text binding not working?


The binding to the ItemsSource list is working. I can tell because the list contains four items and, when I test, my flyout menu also has four items. The problem is each MenuFlyoutItem is blank. In the code below, SourceForCompaniesList is an ObservableCollection of type Company. CompanyName is a string property of Company. I have successfully binded to this list in combo boxes, but I cannot make it work in the flyout menu. Can someone please tell me what I'm doing wrong?

<FlyoutBase.AttachedFlyout>
    <Flyout helpers:BindableFlyout.ItemsSource="{Binding ElementName=thePage, Path=DataContext.SourceForCompaniesList}" x:Name="theFlyout">
        <helpers:BindableFlyout.ItemTemplate>
            <DataTemplate>
                <MenuFlyoutItem Text="{Binding ElementName=theFlyout,Path=DataContext.CompanyName}" />
            </DataTemplate>                                                             
        </helpers:BindableFlyout.ItemTemplate>
    </Flyout>                                                       
</FlyoutBase.AttachedFlyout>

Screenshot of open menu:

Screenshot of open menu


Solution

  • The item Text binding can be rewritten in a simpler way which should work correctly:

    <FlyoutBase.AttachedFlyout>
        <Flyout helpers:BindableFlyout.ItemsSource="{Binding ElementName=thePage, Path=DataContext.SourceForCompaniesList}" x:Name="theFlyout">
            <helpers:BindableFlyout.ItemTemplate>
                <DataTemplate>
                    <MenuFlyoutItem Text="{Binding CompanyName}" />
                </DataTemplate>                                                             
            </helpers:BindableFlyout.ItemTemplate>
        </Flyout>                                                       
    </FlyoutBase.AttachedFlyout>
    

    Note I am using just CompanyName, as the context of the DataTemplate is actually a single Company from the bound items source, so you are binding relative to the company item itself.

    Note, to get an even better performance, you can use x:DataType and x:Bind:

    <FlyoutBase.AttachedFlyout>
        <Flyout helpers:BindableFlyout.ItemsSource="{Binding ElementName=thePage, Path=DataContext.SourceForCompaniesList}" x:Name="theFlyout">
            <helpers:BindableFlyout.ItemTemplate>
                <DataTemplate x:DataType="YourXmlNamespace:Company">
                    <MenuFlyoutItem Text="{x:Bind CompanyName}" />
                </DataTemplate>                                                             
            </helpers:BindableFlyout.ItemTemplate>
        </Flyout>                                                       
    </FlyoutBase.AttachedFlyout>
    

    Where you need to declare the YourXmlNamespace in the root element (most likely a Page) as a xmlns namespace. This version is more performant, as it uses compiled binding (x:Bind) instead of reflection-based Binding.