WPF 명령 새로 고침
누구든지 내가 CanExecute
사용자 지정 명령 (Josh Smith 's RelayCommand
) 에 대해 강제 로 호출 할 수있는 방법을 알고 있습니까?
일반적으로 CanExecute
UI에서 상호 작용이 발생할 때마다 호출됩니다. 무언가를 클릭하면 명령이 업데이트됩니다.
나는 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; }
CommandManager.InvalidateRequerySuggested()
오래 전에 CommandManager.InvalidateRequerySuggested ()를 알고 사용했지만 가끔씩 작동하지 않았습니다. 나는 이것이 왜 그런지 마침내 알아 냈다! 다른 액션처럼 던지지 않더라도 메인 스레드에서 호출해야합니다.
백그라운드 스레드에서 호출하면 작동하는 것처럼 보이지만 때때로 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 );
도움이되기를 바랍니다.
-마이클
GalaSoft.MvvmLight.CommandWpf.RelayCommand를 하나만 업데이트하려면 다음을 사용할 수 있습니다.
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(); }));
}
}
참고 URL : https://stackoverflow.com/questions/783104/refresh-wpf-command
'Programing' 카테고리의 다른 글
경로 가드에 매개 변수 전달 (0) | 2020.11.04 |
---|---|
Type의 기본 생성자를 얻는 가장 효율적인 방법 (0) | 2020.11.04 |
정밀도 수준이 다른 Date 객체 비교 (0) | 2020.11.04 |
SQL * Plus를 사용하여 Oracle 11g에서 데이터베이스를 표시하는 방법 (0) | 2020.11.04 |
Maven에서 카테고리별로 JUnit 테스트를 실행하는 방법은 무엇입니까? (0) | 2020.11.04 |