WPF使用CheckBox和Command禁用菜单元素

2izufjch  于 2022-11-18  发布在  其他
关注(0)|答案(1)|浏览(124)

我有两个菜单项,“消息”和“检查”。“检查”是可检查的,并且在标题附近有一个复选框。我想通过单击“检查”取消选中它,并禁用“消息”项。同时,我想通过单击和使用快捷方式来完成。我写了一些附加类,如RelayCommand

public class RelayCommand : ICommand
{
    private Action<object> _execute;
    private Func<object, bool> _canExecute;

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        _canExecute = canExecute;
        _execute = execute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null || _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}

可观察对象(类似于INotifyOnPropertyChanged)

public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

和MainViewModel类

public class MainViewModel : ObservableObject
    {
        private readonly MainWindow _mainWindow;
        private bool _isChecked { get; set; } = true;

        public bool IsChecked
        {
            get
            {
                return _isChecked;
            }
            set
            {
                _isChecked = value;
                OnPropertyChanged();
            }
        }
   
        public RelayCommand Check { get; set; }
        public MainViewModel(MainWindow mainwindow)
        {
            _mainWindow = mainwindow;

            IsChecked = false;
            Check = new RelayCommand(o =>
            {
                if (IsChecked == false)
                {
                    _mainWindow.Message_menu_item.IsEnabled = true;
                    IsChecked = true;
                }
                else
                {
                    _mainWindow.Message_menu_item.IsEnabled = false;
                    IsChecked = false;
                }
            });
        }
}

我的xaml

<MenuItem Header="File">
            <MenuItem 
                      Name="Message_menu_item"
                      InputGestureText="Ctrl+M"
                      Header="_Message"/>
            <MenuItem
                      Name="Check_menu_item"
                      InputGestureText="Ctrl+C"
                      Command="{Binding Check}"
                      Header="Check"
                      IsCheckable="True"
                      IsChecked="{Binding IsChecked}"/>
            <Separator />
            <MenuItem Header="Exit"
                      InputGestureText="Ctrl+E"/>
            
        </MenuItem>

和装订

<KeyBinding Key="C" Modifiers="Ctrl" Command="{Binding Check}"/>

我想启动一个复选框已选中且“消息”菜单项可用的应用程序,但它是以未选中状态启动的,通过单击它,它只是禁用消息,并忽略复选框(它只工作的一个,再次点击它不会改变任何事情)。它只工作正常使用快捷方式,但我只能使用快捷方式后,点击菜单下拉按钮“文件”在我的情况下(就像这样,如果是关闭快捷方式就不工作

)我不明白为什么它的工作方式如此怪异,请帮帮忙。

qpgpyjmq

qpgpyjmq1#

我想启动复选框已选中的应用程序
如果是这样,您应该相应地更改viewmodel构造函数中的初始化IsChecked = false;
复选框的 * 怪异 * 行为是从Check命令修改IsChecked,并将其绑定到菜单项的IsChecked属性而不指定模式(这导致双向绑定)的结果。因此,当使用菜单时,该属性被切换两次:通过命令和通过绑定。使用键绑定是有效的,因为它只触发命令。
要解决此问题,请将绑定模式更改为OneWay,或者不更改命令中的属性值。
此外:您应该从视图模型中删除对窗口的引用,这可以通过将消息菜单项的IsEnabled属性绑定到视图模型上的另一个属性来实现,如下所示:

public bool IsMessageMenuEnabled => !this.IsChecked;

public bool IsChecked
{
    get => this.isChecked;
    set
    {
        this.isChecked = value;
        this.OnPropertyChanged();
        this.OnPropertyChanged(nameof(this.IsMessageMenuEnabled));
    }
}

相关问题