为什么我的按钮更新为启用后,命令完成?



我现在正在研究命令,我现在所做的是,我做了一个命令,将它绑定到一个按钮,我已经传递了一个bool属性,这将表明按钮是否可以执行命令。

问题是,按钮开始启用,只要我点击它,它变成禁用,然后这个人被添加到ListView,但按钮保持禁用。

我不确定我是否需要在命令中添加UpdateSourceTrigger,我认为实现ObservableObject的全部意义是不必这样做。

实现我想要达到的目标的正确方法是什么?

的命令
public class RelayCommand : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
}

主窗口(DataContext)

<Window x:Class="Commands.MainWindow"
...
Title="MainWindow"
Height="450"
Width="800">
<Window.DataContext>
<viewmodel:MainViewModel />
</Window.DataContext>
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center">
<ListView MinHeight="100"
ItemsSource="{Binding PeopleCollection}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Content="Add"
Width="100"
Height="25"
Command="{Binding AddPersonCommand}" />
</StackPanel>
</Window>

MainViewModel

internal class MainViewModel : ObservableObject
{
public ObservableCollection<PersonModel> PeopleCollection { get; set; }
/* A slow working command */
public RelayCommand AddPersonCommand { get; set; }

private bool _canExecute;
public bool CanExecute
{
get { return _canExecute; }
set
{
_canExecute = value;
NotifyPropertyChanged("CanExecute");
}
}

public MainViewModel()
{
CanExecute = true;
PeopleCollection = new ObservableCollection<PersonModel>();
AddPersonCommand = new RelayCommand(o => AddPersonToCollection(o), (p) => CanExecute);
}
private async void AddPersonToCollection(object o)
{
CanExecute = false;
await Task.Factory.StartNew(() =>
{
/* Simulate a heavy workload*/
Thread.Sleep(5000);
Application.Current.Dispatcher.BeginInvoke(() =>
{
PeopleCollection.Add(new PersonModel
{
Id = 0,
Name = "Foo bar"
});
});
/* Property needs to be updated from the main thread? */
//CanExecute = false;
});
CanExecute = false;
}
}

ObservableObject

internal class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] String propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

我看不到你的Button实际上是如何被标记为禁用的。我看到CanExecutebool被操纵,但你的按钮没有IsEnabled绑定。即使是这种情况,正如@PaulSinnema所说,您只将CanExecute设置为false(除了构造函数中的第一个设置)。我建议尝试在中设置CanExecute = trueTask和lambda函数内(在BeginInvoke中),这样您就可以确保时间是正确的。正如您目前所拥有的,您的AddPersonToCollection方法正在执行以下操作:

  1. 设置CanExecute为false
  2. 触发一个任务并等待它完成
  3. 设置CanExecute为false

这是我的建议,希望能有所帮助:

private async void AddPersonToCollection(object o)
{
CanExecute = false;
await Task.Factory.StartNew(() =>
{
/* Simulate a heavy workload*/
Thread.Sleep(5000);
Application.Current.Dispatcher.BeginInvoke(() =>
{
PeopleCollection.Add(new PersonModel
{
Id = 0,
Name = "Foo bar"
});
// Setting it here ensures we flip it as soon as the collection has a person added
CanExecute = true;
});


});
// Remove this line
///CanExecute = false;
}

最新更新