默认情况下,菜单项在无法执行命令时会被禁用(CanExecute = false)。根据CanExecute方法使菜单项可见/折叠的最简单方法是什么?
答案 0 :(得分:51)
感谢您的解决方案。对于那些想要显式XAML的人来说,这可能有所帮助:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
</Window.Resources>
<ContextMenu x:Key="innerResultsContextMenu">
<MenuItem Header="Open"
Command="{x:Static local:Commands.AccountOpened}"
CommandParameter="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"
CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"
Visibility="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}, Mode=OneWay, Converter={StaticResource booleanToVisibilityConverter}}"
/>
</ContextMenu>
在我的情况下,上下文菜单是一个资源,因此可见性的绑定必须使用RelativeSource自绑定设置。
作为一方,对于CommandParameter,您还可以传递单击项目的DataContext以打开上下文菜单。并且为了将命令绑定路由到父窗口,您还需要相应地设置CommandTarget。
答案 1 :(得分:44)
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
CanExecute
切换IsEnabled
属性,因此只需观看此内容并将所有内容保留在用户界面中。如果要重复使用,请创建单独的样式。
答案 2 :(得分:43)
您可以简单地将Visibility绑定到IsEnabled(在CanExecute == false时设置为false)。 你仍然需要一个IValueConverter来将bool转换为visible / collapsed。
public class BooleanToCollapsedVisibilityConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//reverse conversion (false=>Visible, true=>collapsed) on any given parameter
bool input = (null == parameter) ? (bool)value : !((bool)value);
return (input) ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
答案 3 :(得分:8)
Microsoft提供BooleanToVisibilityConverter http://msdn.microsoft.com/en-us/library/system.windows.controls.booleantovisibilityconverter.aspx
答案 4 :(得分:1)
我不知道这是否是最简单的方法,但您始终可以创建一个返回CanExecute()
的属性,然后使用IValueConverter
将元素的可见性绑定到此属性将布尔值转换为可见性。
答案 5 :(得分:0)
将可见性绑定到IsEnabled可以解决问题,但所需的XAML却又长又复杂:
Visibility="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}, Mode=OneWay, Converter={StaticResource booleanToVisibilityConverter}}"
您可以使用附加属性隐藏所有绑定详细信息,并清楚传达您的意图。
这是附加的属性:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace MyNamespace
{
public static class Bindings
{
public static bool GetVisibilityToEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(VisibilityToEnabledProperty);
}
public static void SetVisibilityToEnabled(DependencyObject obj, bool value)
{
obj.SetValue(VisibilityToEnabledProperty, value);
}
public static readonly DependencyProperty VisibilityToEnabledProperty =
DependencyProperty.RegisterAttached("VisibilityToEnabled", typeof(bool), typeof(Bindings), new PropertyMetadata(false, OnVisibilityToEnabledChanged));
private static void OnVisibilityToEnabledChanged(object sender, DependencyPropertyChangedEventArgs args)
{
if (sender is FrameworkElement element)
{
if ((bool)args.NewValue)
{
Binding b = new Binding
{
Source = element,
Path = new PropertyPath(nameof(FrameworkElement.IsEnabled)),
Converter = new BooleanToVisibilityConverter()
};
element.SetBinding(UIElement.VisibilityProperty, b);
}
else
{
BindingOperations.ClearBinding(element, UIElement.VisibilityProperty);
}
}
}
}
}
这是您将如何使用它:
<Window x:Class="MyNamespace.SomeClass"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace">
<ContextMenu x:Key="bazContextMenu">
<MenuItem Header="Open"
Command="{x:Static local:FooCommand}"
local:Bindings.VisibilityToEnabled="True"/>
</ContextMenu>
</Window>