如何仅在图像的来源 属性 不为空时启用上下文菜单项?

How do I enable context menu items only when an Image's Source property is not null?

当图像的 Source 属性 不为空时,仅启用上下文菜单项的最佳方法是什么?这是 XAML:

    <Window.Resources>
        <local:IsNullValueConverter x:Key="IsNullValueConverter" />
        <local:NotNullValueConverter x:Key="NotNullValueConverter" />
    </Window.Resources>
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <Button Content="Fill" IsEnabled="{Binding ElementName=TheImage, Path=Source, Converter={StaticResource IsNullValueConverter}}" Click="Fill_Click" />
            <Button Content="Erase" IsEnabled="{Binding ElementName=TheImage, Path=Source, Converter={StaticResource NotNullValueConverter}}" Click="Erase_Click" />
        </StackPanel>
        <Grid DockPanel.Dock="Bottom" Background="White">
            <Grid.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Fill" IsEnabled="{Binding ElementName=TheImage, Path=Source, Converter={StaticResource IsNullValueConverter}}" Click="Fill_Click" />
                    <MenuItem Header="Erase" IsEnabled="{Binding ElementName=TheImage, Path=Source, Converter={StaticResource NotNullValueConverter}}" Click="Erase_Click" />
                </ContextMenu>
            </Grid.ContextMenu>
            <Image Name="TheImage" />
        </Grid>
    </DockPanel>

这是代码:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Fill_Click(object sender, RoutedEventArgs e)
        {
            int width = 1;
            int height = 1;
            var format = PixelFormats.Gray8;
            var pixels = new byte[width * height * (format.BitsPerPixel / 8)];
            TheImage.Source = BitmapSource.Create(width, height, 96.0, 96.0, format, null, pixels, width * (format.BitsPerPixel / 8));
        }

        private void Erase_Click(object sender, RoutedEventArgs e)
        {
            TheImage.Source = null;
        }
    }

    public class IsNullValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value == null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class NotNullValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value != null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

这些按钮的反应完全符合我的要求:最初只启用填充,然后一旦您单击它并且图像被填充,它就会被禁用,同时启用擦除。然而,上下文菜单项在整个过程中都处于启用状态,尽管它们的 IsEnabled 属性使用与按钮完全相同的绑定。

我尝试了很多不同的解决方案,最终找到了一些简单有效的方法:

<MenuItem Header="Fill" IsEnabled="{Binding Source={x:Reference TheImage}, Path=Source, Converter={StaticResource IsNullValueConverter}}" Click="Fill_Click" />
<MenuItem Header="Erase" IsEnabled="{Binding Source={x:Reference TheImage}, Path=Source, Converter={StaticResource NotNullValueConverter}}" Click="Erase_Click" />

或者,可以将其添加到代码中(必须命名上下文菜单),但在 XAML 中这样做似乎更加优雅。

NameScope.SetNameScope(TheContextMenu, NameScope.GetNameScope(this));

感谢 ZSH 为我指明了正确的方向。