sourcetip

Refresh WPF 명령어

fileupload 2023. 4. 18. 23:15
반응형

Refresh WPF 명령어

어떻게 하면 내가 강제로CanExecute커스텀 커맨드(Josh Smith's)로 호출할 수 있습니까?

일반적으로.CanExecuteUI에서 상호 작용이 발생할 때마다 호출됩니다.어떤 항목을 클릭하면 명령어가 업데이트됩니다.

저는 지금 조건이...CanExecute뒤에서 타이머가 켜지거나 꺼집니다.이는 사용자의 조작에 의한 것이 아니기 때문에CanExecute는 사용자가 UI와 상호 작용할 때까지 호출되지 않습니다.최종 결과는 나의Button는 사용자가 클릭할 때까지 활성화/비활성화된 상태로 유지됩니다.클릭 후 올바르게 갱신됩니다.때때로 그Button이네이블로 표시되어 있습니다만, 유저가 클릭하면 기동하지 않고 디세이블로 바뀝니다.

타이머에 의해 영향을 받는 속성이 변경되었을 때 강제로 코드로 업데이트를 하려면 어떻게 해야 합니까?CanExecute쏘려고 했는데PropertyChanged(INotifyPropertyChanged영향을 주는 속성에 대해서)CanExecute하지만 그것은 도움이 되지 않았다.

XAML의 예:

<Button Content="Button" Command="{Binding Cmd}"/>

뒤에 있는 코드 예:

private ICommand m_cmd;
public ICommand Cmd
{
    if (m_cmd == null)
        m_cmd = new RelayCommand(
            (param) => Process(),
            (param) => EnableButton);

    return m_cmd;
}

// Gets updated from a timer (not direct user interaction)
public bool EnableButton { get; set; }

호출하면 Command Manager는 강제로 Requery Suggested 이벤트를 발생시킵니다.

비고:CommandManager는 키보드 포커스 변경 등 명령어타깃이 변경된 시기를 판단할 때 특정 조건에만 주의를 기울입니다.명령어를 실행할 수 없는 상황의 변경을 Command Manager가 충분히 판단하지 못한 경우 InvalidateRequerySquested를 호출하여 강제로 RequerySquested 이벤트를 발생시킬 수 있습니다.

Command Manager를 알고 있었습니다.Invalidate Requery Suggested()는 오래 전에 사용했지만 가끔 작동하지 않았습니다.왜 그랬는지 이제야 알았어요!비록 다른 액션처럼 던지지는 않지만, 여러분은 그것을 본론으로 불러야 합니다.

백그라운드 스레드에서 호출하면 동작하는 것처럼 보이지만 UI가 비활성화되어 있을 수 있습니다.나는 이것이 누군가에게 도움이 되고, 내가 방금 낭비한 시간을 절약해 주길 바란다.

이를 위한 회피책은 바인딩입니다.IsEnabled속성:

<Button Content="Button" Command="{Binding Cmd}" IsEnabled="{Binding Path=IsCommandEnabled}"/>

이 속성을 ViewModel에 구현합니다.또한 UnitTesting은 명령어가 아닌 속성으로 동작하여 명령어를 특정 시점에서 실행할 수 있는지 확인할 수 있습니다.

저는 개인적으로 그게 더 편해요.

아마도 이 변종이 고객에게 적합할 것입니다.

 public interface IRelayCommand : ICommand
{
    void UpdateCanExecuteState();
}

구현:

 public class RelayCommand : IRelayCommand
{
    public event EventHandler CanExecuteChanged;


    readonly Predicate<Object> _canExecute = null;
    readonly Action<Object> _executeAction = null;

   public RelayCommand( Action<object> executeAction,Predicate<Object> canExecute = null)
    {
        _canExecute = canExecute;
        _executeAction = executeAction;
    }


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

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



    public void Execute(object parameter)
    {
        if (_executeAction != null)
            _executeAction(parameter);
        UpdateCanExecuteState();
    }
}

간단한 사용:

public IRelayCommand EditCommand { get; protected set; }
...
EditCommand = new RelayCommand(EditCommandExecuted, CanEditCommandExecuted);

 protected override bool CanEditCommandExecuted(object obj)
    {
        return SelectedItem != null ;
    }

    protected override void EditCommandExecuted(object obj)
    {
        // Do something
    }

   ...

    public TEntity SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value;

            //Refresh can execute
            EditCommand.UpdateCanExecuteState();

            RaisePropertyChanged(() => SelectedItem);
        }
    }

XAML:

<Button Content="Edit" Command="{Binding EditCommand}"/>

조언해줘서 고마워요BG 스레드에서 UI 스레드로 콜을 정리하는 방법은 다음과 같습니다.

private SynchronizationContext syncCtx; // member variable

컨스트럭터:

syncCtx = SynchronizationContext.Current;

백그라운드 스레드에서 재쿼리를 트리거하려면 다음 절차를 수행합니다.

syncCtx.Post( delegate { CommandManager.InvalidateRequerySuggested(); }, null );

도움이 됐으면 좋겠다.

-- 마이클

단일 Gala Soft만 업데이트.MvvmLight.CommandWpf.사용할 수 있는 Relay Command

mycommand.RaiseCanExecuteChanged();

그리고 저는 Extension 메서드를 만들었습니다.

public static class ExtensionMethods
    {
        public static void RaiseCanExecuteChangedDispatched(this RelayCommand cmd)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => { cmd.RaiseCanExecuteChanged(); }));
        }

        public static void RaiseCanExecuteChangedDispatched<T>(this RelayCommand<T> cmd)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => { cmd.RaiseCanExecuteChanged(); }));
        }
    }

여기에 언급되어 있는 것을 보지 못했기 때문에 2023년에 추가했습니다.

이 문제를 해결하기 위해 NuGet(VS에서 "Delegate Command"에 권장)을 사용하여 프리즘 라이브러리를 설치했습니다.RelayCommand실행.난 그냥 내가 부르던 대로 전화했어. 나한테는 잘된 일이야.

언급URL : https://stackoverflow.com/questions/783104/refresh-wpf-command

반응형