在 XAML / WP8.1 中的 DataTemplate 中绑定 Flyout MenuItem 的可见性

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

我想将 Flyout MenuItem 上的 Visibility 属性 绑定到我的 ViewModel 上的布尔值。这是我的 ViewModel 和相关代码:

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();
        }
    }
}

这是我的 XAML 代码:

<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>

我不知道为什么,但这不起作用!在其他布尔值上,我的 BooleanToVisibilityConverter 工作得很好!

首先,为了能够绑定到它,AlreadyUploaded 应该是一个 属性 而不是一个字段:

public bool AlreadyUploaded { get; set; }

此外,您应该按照 Burak Kaan Köse 的建议实施 INotifyPropertyChanged,并在 AlreadyUploaded 属性 发生变化时引发 PropertyChanged 事件,以便报告此问题更改为视图。

最后,似乎 AlreadyUploaded 是在您的 View 的全局 ViewModel 中定义的,而您正试图从 DataTemplate 中绑定到它(尽管您的代码片段对此不太清楚)?在这种情况下,您需要显式绑定到视图的 DataContext(即它的 ViewModel)。

您可以执行后者,例如,为包含所有其他元素的页面根网格分配一个唯一名称,例如:

<Grid x:Name="Root">

并显式绑定到此项的 DataContext,这与视图的全局 DataContext:

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

从上面的 XAML 来看,您的 Flyout 似乎在 DataTemplate 中。根据您声明此 DataTemplate 的位置以及设置控件的 DataContext 的位置,可能未设置 MenuFlyout 的 DataContext。这将解释您所看到的行为。也许作为调试步骤,您可以订阅 MenuFlyout 上的 DataContextChanged 事件,并查看何时命中该代码。这将帮助您确保确实设置了 MenuFlyout 的 DataContext。希望这可以帮助! 安德鲁