Bind Flyout MenuItem's Visibility within a DataTemplate in XAML / WP8.1

357 Views Asked by At

I want to bind the Visibility property on a Flyout MenuItem to a Boolean value on my ViewModel. Here is my ViewModel and related code:

public class AppVM
{
    public ObservableCollection<RecordFileVm> Files { get; set; }
    public bool AlreadyUploaded = false;
}

namespace App.Common.XAML_Helpers
{
    public class BooleanToVisibilityConverter : IValueConverter
    {
        private static object GetVisibility(object value)
        {
            if (!(value is bool))
            {
                return Visibility.Collapsed;
            }

            var objValue = (bool)value;

            return objValue ? Visibility.Visible : Visibility.Collapsed;
        }
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return GetVisibility(value);
        }
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }
}

And here is the XAML code I have:

<DataTemplate x:Key="TemplateRecordedFiles">
    <!-- other code here -->
    <FlyoutBase.AttachedFlyout>
        <MenuFlyout>
            <MenuFlyoutItem x:Name="RemoveItem"
                Text="Delete Item"
                Click="RemoveItem_OnClick"/>
            <MenuFlyoutItem x:Name="UploadItem"
                Text="Upload Item"
                Click="UploadItem_OnClick" Visibility="{Binding AlreadyUploaded, Converter = {StaticResource BoolToVis}}"/>
        </MenuFlyout>
    </FlyoutBase.AttachedFlyout>
</DataTemplate>

I don't know why, but this isn't working! And on other boolean values, my BooleanToVisibilityConverter works just fine!

2

There are 2 best solutions below

1
On BEST ANSWER

First of all, to be able to bind to it, AlreadyUploaded should be a property instead of a field:

public bool AlreadyUploaded { get; set; }

In addition, you should implement INotifyPropertyChanged as Burak Kaan Köse suggested and raise the PropertyChanged event whenever the AlreadyUploaded property has changed, in order to report this change to the View.

Finally, it seems that AlreadyUploaded is defined in your View's global ViewModel, while you are trying to bind to it from within a DataTemplate (although your code snippet is not too clear about this)? In this case, you need to explicitly bind to the View's DataContext (which is its ViewModel).

You can do the latter by, for example, assign a unique name to the pages root grid that contains all the other elements, e.g.:

<Grid x:Name="Root">

and explicitly bind to this item's DataContext, which is the same as the View's global DataContext:

Visibility="{Binding ElementName=Root, Path=DataContext.Show, Converter={StaticResource BoolToVis}}"
0
On

From looking at the XAML above, it looks like you have your Flyout in a DataTemplate. Depending on where you have declared this DataTemplate and where the DataContext for the control is set, the DataContext for the MenuFlyout may be not set. This would explain the behavior you are seeing. Maybe as a debugging step you can subscribe to the DataContextChanged event on the MenuFlyout, and see when that code is hit. This will help you ensure that the DataContext of the MenuFlyout is indeed being set. Hope this helps! Andrew