programing

WPF - 명령의 CanExecute가 false일 경우 메뉴 항목을 숨기는 방법

showcode 2023. 4. 20. 23:25
반응형

WPF - 명령의 CanExecute가 false일 경우 메뉴 항목을 숨기는 방법

명령을 실행할 수 없는 경우 기본적으로 메뉴 항목은 비활성화됩니다(CanExecute = false).CanExecute 메서드에 따라 메뉴 항목을 표시/축소하는 가장 쉬운 방법은 무엇입니까?

해결해주셔서 감사합니다.명시적인 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 Self 바인딩 설정을 사용해야 합니다.

한편 CommandParameter의 경우 컨텍스트 메뉴를 열기 위해 클릭한 항목의 DataContext를 전달할 수도 있습니다.명령어 바인딩을 부모창으로 라우팅하려면 그에 따라 명령어타깃도 설정해야 합니다.

<Style.Triggers>
    <Trigger Property="IsEnabled" Value="False">
        <Setter Property="Visibility" Value="Collapsed"/>
    </Trigger>
</Style.Triggers>

CanExecute를 토글하다IsEnabled속성을 확인하시고 UI에 모든 내용을 저장해 두세요.이 유형을 재사용하려면 별도의 유형을 작성하십시오.

가시성을 IsEnabled에 바인딩하기만 하면 됩니다(CanExecute == false에서 false로 설정).부울을 표시/축소 상태로 변환하려면 IValue Converter가 필요합니다.

    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
    }

Microsoft 는 Boolean ToVisibility Converter 를 제공하고 있습니다.
http://msdn.microsoft.com/en-us/library/system.windows.controls.booleantovisibilityconverter.aspx

이것이 가장 쉬운 방법인지는 모르겠지만 언제든지 속성을 생성하여CanExecute()그런 다음 visibility를 사용하여 요소의 visibility를 사용하여IValueConverter부울을 가시성으로 변환합니다.

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>

언급URL : https://stackoverflow.com/questions/3761672/wpf-how-to-hide-menu-item-if-commands-canexecute-is-false

반응형