Проблема с вашим кодом состоит в том, что в свойствах вашей команды используются тела выражений, они выполняются каждый раз, когда кто-то получает свойство, то есть каждый раз, когда вы запрашиваете команду StartServer
, она дает вам новый экземпляр. Вы можете проверить это самостоятельно, поставив точку останова на получателе, и вы увидите, что она будет поражена несколько раз и всегда создаст новый экземпляр команды делегата.
Для того, чтобы ваш код работал, вы должны использоватьровно по одному экземпляру каждой команды, вы можете достичь этого с помощью вспомогательного поля или свойства только для чтения и установить его в conostructor:
public MainWindowViewModel()
{
PropertyChanged += PropertyChangedHandler;
StartServer = new DelegateCommand<object>(
context =>
{
ServerIsRunning = true;
}, e => !ServerIsRunning);
StopServer = new DelegateCommand<object>(
context => {
ServerIsRunning = false;
}, e => ServerIsRunning);
}
public DelegateCommand<object> StartServer
{ get; }
public DelegateCommand<object> StopServer
{ get; }
Пользовательский интерфейс будет прослушивать только возникшее событие CanExecuteChanged
с помощью экземпляра команды, с которой она связана (через Command={Binding ...}
.
Ваш код также может быть упрощен, поскольку вы можете вызывать RaiseCanExecuteChanged
напрямую, вместо того, чтобы вызывать PropertyChangedEvent
и слушать его для себя:
public bool ServerIsRunning
{
get => m_serverIsRunning;
set
{
m_serverIsRunning = value;
StartServer.RaiseCanExecuteChanged();
StopServer.RaiseCanExecuteChanged();
}
}