簡體   English   中英

WPF MVVM 命令可以執行啟用/禁用按鈕

[英]WPF MVVM command canexecute enable/disable button

當文本框屬性文本不為空時,我想啟用 RibbonButton。 當文本框屬性文本為空時禁用 RibbonButton。 我想在 ICommand 中使用 CanExecute 方法。 我該怎么做?

看法:

 <Custom:RibbonButton
                        LargeImageSource="..\Shared\img\save_diskete.png"
                        Label="Save"
                        Command="{Binding ButtonCommand}">
                    </Custom:RibbonButton>

視圖模型

class KomentarViewModel:BaseViewModel
    {
        #region Data
        private ICommand m_ButtonCommand;
        public ICommand ButtonCommand
        {
            get
            {
                return m_ButtonCommand;
            }
            set
            {
                m_ButtonCommand = value;
            }
        }
        private string textKomentar;
        public string TextKomentar
        {
            get
            {
                return this.textKomentar;
            }
            set
            {
                // Implement with property changed handling for INotifyPropertyChanged
                if (!string.Equals(this.textKomentar, value))
                {
                    textKomentar = value;
                    OnPropertyChanged("TextKomentar");
                }
            }
        }        
        private ObservableCollection<Komentar> allCommentsInc;
        public ObservableCollection<Komentar> AllCommentsInc
        {
            get
            {
                return allCommentsInc;
            }
            set
            {
                allCommentsInc = value;
                OnPropertyChanged("AllCommentsInc");
            }
        }

        public int idIncident { get; private set; }
        public Incident incident { get; private set; }
        #endregion

        #region Constructor
        public KomentarViewModel(int id)
        {
            CC_RK2Entities context = new CC_RK2Entities();
            this.idIncident = id;

            AllCommentsInc = new ObservableCollection<Komentar>(context.Komentar.Where(a => a.Incident_id == idIncident));
            incident = context.Incident.Where(a => a.id == idIncident).First();

            //ButtonCommand = new RelayCommand(new Action<object>(ShowMessage));
        }
        #endregion        

        #region Methods
        //ukaz napsany text
        public void ShowMessage(object obj)
        {
            //MessageBox.Show(obj.ToString());
            MessageBox.Show(this.TextKomentar);
        }
}

中繼命令

namespace Admin.Shared.Commands
{
    class RelayCommand : ICommand
    {
        private Action<object> _action;

        public RelayCommand(Action<object> action)
        {
            _action = action;
        }

        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            return true;            
        }

        public event EventHandler CanExecuteChanged;

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

        #endregion
    }
}

你需要像這樣修改你的 RelayCommand 類

  class RelayCommand : ICommand
{
    private Action<object> _action;
    private Func<bool> _func;  

    public RelayCommand(Action<object> action,Func<bool> func)
    {
        _action = action;
        _func = func;
    }

    public void RaiseCanExecuteChanged()
    {
        if(CanExecuteChanged!=null)
            CanExecuteChanged(this,new EventArgs());
    }

    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        if (_func != null)
           return _func();
        return true;
    }



    public event EventHandler CanExecuteChanged;

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

    #endregion
}

將 ButtonCommand 初始化為

ButtonCommand = new RelayCommand((s) => ShowMessage(s),()=>!string.IsNullOrEmpty(TextKomentar));

從 Text 屬性的設置器 RaiseCanExcuteChanged

        public string TextKomentar
    {
        get
        {
            return this.textKomentar;
        }
        set
        {
            // Implement with property changed handling for INotifyPropertyChanged
            if (!string.Equals(this.textKomentar, value))
            {
                textKomentar = value;
                OnPropertyChanged("TextKomentar");
            }
            ButtonCommand.RaiseCanExecuteChanged();
        }
    }

為 canexecute 實現這個:

public bool CanExecute(object parameter)
        {if(thistext available)
            return true; 
         else
            return false;  
        }

因為, CanExecuteChanged當引發CanExecute的方法ICommand得到改變。 當某些可能更改canexecute命令時,它會被調用。 並且可以執行更改應更改為:

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

編輯

在您的視圖模型構造函數中:

m_ButtonCommand= new RelayCommand(Submit, CanSubmit);

now method for this submit:
 private bool CanSubmit(object obj)
        {
            if(thistext available)
                return true; 
             else
                return false;  

        }
 public void Submit(object _)
  {//... code}

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

像這樣做。

簡而言之,您需要以下內容:

  1. 讓我們首先創建我們自己的delegate命令:
public class DelegateCommand : DelegateCommandBase
{
    private Action _executeMethod;
    private Func<bool> _canExecute;
    
    public DelegateCommand(Action executeMethod)
        : this(executeMethod, () => true) {}
   
    public DelegateCommand(Action executeMethod, Func<bool> _canExecute): base()
    {
        if (executeMethod == null || _canExecute == null) {         
              throw new ArgumentNullException(nameof(executeMethod),      
                              Resources.DelegateCommandDelegatesCannotBeNull);
        }

        _executeMethod = executeMethod;
        _canExecute = _canExecute;
    }

    public void Execute() => _executeMethod();  
    public bool CanExecute() => _canExecute();
    
    protected override void Execute(object parameter) => Execute();
    protected override bool CanExecute(object parameter) => CanExecute();

    public DelegateCommand ObservesProperty<T>(Expression<Func<T>> propertyExpression)
    {
        ObservesPropertyInternal(propertyExpression);
        return this;
    }
    
    public DelegateCommand ObservesCanExecute(Expression<Func<bool>> canExecuteExpression)
    {
        _canExecute = canExecuteExpression.Compile();
        ObservesPropertyInternal(canExecuteExpression);
        return this;
    }
}

這里, DelegateCommandBase實際上來自Prism.Commands命名空間。

如果您不使用Prism作為 WPF 的 MVVM 框架,您可以創建自己的DelegateCommandBase副本(在此處查找解決方案)。

  1. 在您的視圖模型中,創建一個類型為DelegateCommand的成員並在構造函數中對其進行初始化:
public class MyViewModel
{
    private DelegateCommand _okCommand;
    public DelegateCommand OkCommand
    {
        get => _okCommand;
        set => SetProperty(ref _okCommand, value);
    }
        
    public MyViewModel() 
    {
        OkCommand = new PrismCommands.DelegateCommand(OkCommandHandler,
                                                      OkCanExecuteCommandHandler);
    }
    
    private void OkCommandHandler()
    {
        // ...
    } 
    
    // This is important part: need to return true/false based
    // on the need to enable or disable item
    private bool OkCanExecuteCommandHandler() =>
        return some_condition_to_enable_disable_item;   
}

注意:確保每次發生可能影響some_condition_to_enable_disable_item條件行為的更改時引發執行更改事件。

例如,在Prism的情況下,一旦發生與條件相關的更改(在我們的示例中為OkCommand.RaiseCanExecuteChanged(); ),您就可以調用RaiseCanExecuteChanged方法。

小提示:對於 Telerik WPF 控件,您需要調用InvalidateCanExecute()而不是RaiseCanExecuteChanged()


最后,我們的XAML將如下所示:

<Button x:Name="btnOk"
        Content="Ok"
        Command="{Binding OkCommand}"/>

上次我使用來自Microsoft.Practices.Prism.dll Microsoft.Practices.Prism.Commands命名空間。 DelegateCommand有自己的RaiseCanExecuteChanged()方法。 因此,好處是您不必編寫自己的ICommand實現。

XAML:

<StackPanel>
    <CheckBox IsChecked="{Binding IsCanDoExportChecked}" />
    <Button Command="{Binding ExportCommand}" Content="Export" />
</StackPanel>

視圖模型:

public class ViewModel
{
    public DelegateCommand ExportCommand { get; }

    public ViewModel()
    {
        ExportCommand = new DelegateCommand(Export, CanDoExptor);
    }

    private void Export()
    {
        //logic
    }

    private bool _isCanDoExportChecked;

    public bool IsCanDoExportChecked
    {
        get { return _isCanDoExportChecked; }
        set
        {
            if (_isCanDoExportChecked == value) return;

            _isCanDoExportChecked = value;
            ExportCommand.RaiseCanExecuteChanged();
        }
    }

    private bool CanDoExptor()
    {
        return IsCanDoExportChecked;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM