WPF-CommandBindings를 통해 명령이 'CanExecute'를 다시 평가하도록하는 방법


130

나는이 Menu각각의 경우 MenuItem계층 구조에서 그 한 Command속성은 설정 RoutedCommand내가 정의한합니다. 연관된 것은 각각의 활성화 된 상태를 제어하는 CommandBinding평가를위한 콜백을 제공합니다 .CanExecuteMenuItem

이것은 거의 작동합니다. 메뉴 항목은 처음에 올바른 활성화 및 비활성화 상태로 나타납니다. 그러나 CanExecute콜백에서 사용 하는 데이터가 변경되면이 새로운 상태가 UI에 반영되도록 콜백에서 결과를 다시 요청하는 명령이 필요합니다.

에 공개 방법이있을 나타나지 않습니다 RoutedCommand또는 CommandBinding이합니다.

콜백은 클릭하거나 컨트롤에 입력 할 때 다시 사용됩니다 (마우스 오버로 인해 새로 고침이 발생하지 않기 때문에 입력시 트리거되는 것 같습니다).

답변:


172

이 책에서 가장 예쁘지는 않지만 CommandManager를 사용하여 모든 명령 바인딩을 무효화 할 수 있습니다.

CommandManager.InvalidateRequerySuggested();

MSDN에 대한 추가 정보보기


1
고마워 이것은 잘 작동했습니다. UI에는 약간의 지연이 있지만 걱정할 필요는 없습니다. 또한 귀하의 답변을 즉각 표명 한 다음 투표가 다시 이루어 졌는지 확인했습니다. 이제 효과가 있으므로 투표를 다시 신청할 수 없습니다. 왜 SO가 그 규칙을 가지고 있는지 확실하지 않습니다.
Drew Noakes

5
투표를 다시 적용하기 위해 답변을 편집했습니다. 편집 내용을 변경하지 않았습니다. 다시 감사합니다.
Drew Noakes

코드 숨김에서 Texbox의 내용을 변경할 때도 같은 문제가 발생했습니다. 손으로 편집하면 작동합니다. 이 응용 프로그램에서는 팝업되는 컨트롤에 의해 texbox를 편집하고 팝업을 저장하면 Texbox.Text 속성이 변경됩니다. 이것은 문제를 해결했다! 감사합니다 @Arcturus
Dzyann

10
다른 답변 ( stackoverflow.com/questions/783104/refresh-wpf-command )에서 "UI 스레드에서 호출해야합니다"
Samvel Siradeghyan

84

나중에 이것을 만나는 사람에게는; MVVM 및 Prism을 사용하는 경우 Prism의 DelegateCommand구현은 이를 수행 ICommand하는 .RaiseCanExecuteChanged()방법을 제공합니다 .


12
이 패턴은 다른 MVVM 라이브러리에서도 볼 수 있습니다 (예 : MVVM Light).
Peter Lillevold 2016 년

2
Prism과 달리 MVVM Light v5의 소스 코드는 RaiseCanExecuteChanged() 단순히 호출을 나타냅니다 CommandManager.InvalidateRequerySuggested().
피터

4
WPF에서 MVVM 빛에 보조 노트, 당신은 문제의 원인이됩니다 GalaSoft.MvvmLight.Command 이후 네임 스페이스 GalaSoft.MvvmLight.CommandWpf를 사용할 필요가 mvvmlight.net/installing/changes#v5_0_2
fuchs777

((RelayCommand)MyCommand).RaiseCanExecuteChanged();GalaSoft.MvvmLight.Command를 사용하여 나를 위해 일했습니다. 그러나로 변경 한 후에 CommandWPF는 아무것도 호출하지 않아도 작동했습니다. 감사합니다 @ fuchs777
Robin Bennett

1
그래도 타사 라이브러리를 사용하지 않으면 어떻게됩니까?
Vidar

28

CommandManager.InvalidateRequerySuggested();성능이 저하되어 사용할 수 없었습니다.

내가 사용하고 MVVM 도우미 외모가 아래처럼 '의 위임 명령을, (나는 그것을 우리 REQ에 대한 약간 불통있다). 당신은 command.RaiseCanExecuteChanged()VM 에서 전화해야합니다

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

/// <summary>
/// This method can be used to raise the CanExecuteChanged handler.
/// This will force WPF to re-query the status of this command directly.
/// </summary>
public void RaiseCanExecuteChanged()
{
    if (canExecute != null)
        OnCanExecuteChanged();
}

/// <summary>
/// This method is used to walk the delegate chain and well WPF that
/// our command execution status has changed.
/// </summary>
protected virtual void OnCanExecuteChanged()
{
    EventHandler eCanExecuteChanged = _internalCanExecuteChanged;
    if (eCanExecuteChanged != null)
        eCanExecuteChanged(this, EventArgs.Empty);
}

3
참고로 CommandManager.RequerySuggested + = value; 어떤 이유로 CanExecute 코드에 대해 거의 일정한 / 루핑 평가를 받고있었습니다. 그렇지 않으면 솔루션이 예상대로 작동했습니다. 감사!
robaudas

15

자신의 클래스를 구현 한 롤을 구현 ICommand한 경우 많은 자동 상태 업데이트를 잃을 수 있으므로 필요한 것보다 수동으로 새로 고침해야합니다. 또한 고장날 수 있습니다 InvalidateRequerySuggested(). 문제는 간단한 ICommand구현으로 새 명령을에 연결하지 못한다는 것 CommandManager입니다.

해결책은 다음을 사용하는 것입니다.

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

    public void RaiseCanExecuteChanged()
    {
        CommandManager.InvalidateRequerySuggested();
    }

이 방법으로 가입자는 CommandManager수업 대신 연결하고 명령 상태 변경에 올바르게 참여할 수 있습니다.


2
간단하고 요점까지 사람들은 ICommand 구현을 제어 할 수 있습니다.
Akoi Meexx

2

명령에 대한 속성 종속성을 처리하는 솔루션을 구현했습니다. 여기 링크는 https : //.com/a/30394333/1716620

덕분에 다음과 같은 명령을 갖게됩니다.

this.SaveCommand = new MyDelegateCommand<MyViewModel>(this,
    //execute
    () => {
      Console.Write("EXECUTED");
    },
    //can execute
    () => {
      Console.Write("Checking Validity");
       return PropertyX!=null && PropertyY!=null && PropertyY.Length < 5;
    },
    //properties to watch
    (p) => new { p.PropertyX, p.PropertyY }
 );

-3

이것이 나를 위해 일한 것입니다 : CanExecute를 XAML의 Command 앞에 두십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.