我在一个Prism / WPF项目中有一个类似这样的ViewModel类。
public class ContentViewModel : ViewModelBase, IContentViewModel
{
public ContentViewModel(IPersonService personService)
{
Person = personService.GetPerson();
SaveCommand = new DelegateCommand(Save, CanSave);
}
public Person Person { get; set; }
public DelegateCommand SaveCommand { get; set; }
private void Save()
{
// Save actions here...
}
private bool CanSave()
{
return Person.Error == null;
}
}以上ViewModel中使用的person类型定义如下:
public class Person : INotifyPropertyChanged, IDataErrorInfo
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
OnPropertyChanged("FirstName");
}
}
// other properties are implemented in the same way as above...
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private string _error;
public string Error
{
get
{
return _error;
}
}
public string this[string columnName]
{
get
{
_error = null;
switch (columnName)
{
// logic here to validate columns...
}
return _error;
}
}
}ContentViewModel的一个实例被设置为视图的DataContext。在视图中,我使用了绑定到Person,如下所示:
<TextBox Text="{Binding Person.FirstName, ValidatesOnDataErrors=True}" />
<Button Content="Save" Command="{Binding SaveCommand}" />当我对绑定到Person的属性(如FirstName )的TextBox进行更改并单击Save时,我可以在ViewModel命令处理程序中看到更改。但是,如果这些属性中的任何一个在验证中失败,CanSave就永远不会执行,按钮也永远不会被禁用。
在上述场景中,如何根据DelegateCommand的CanExecute操作处理程序禁用按钮?
发布于 2012-03-15 13:44:18
尝试对所有可以更改的属性执行以下操作:
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
OnPropertyChanged("FirstName");
OnPropertyChanged("Error");
}
}另一个选择
switch (columnName)
{
// logic here to validate columns...
OnPropertyChanged("Error");
}您遇到的问题是,当错误发生变化时,OnPropertyChanged不会被调用。
下一步是在创建person的属性changes事件时订阅它,并创建一个处理程序来检查属性changes,然后更改命令使用的布尔变量。
public ContentViewModel(IPersonService personService)
{
Person = personService.GetPerson();
Person.PropertyChanged+= PersonPropertyChangedHandler;
SaveCommand = new DelegateCommand(Save, personHasError);
}
bool personHasError = false;
void PersonPropertyChangedHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "Error")
{
if(Person.Error == null)
personHasError = true;
else
personHasError = false;
}
}希望这能起作用。我手工构建了这个,没有检查它,所以让我知道它是否有buggy或其他什么,我会纠正它
发布于 2012-03-14 17:36:37
在ContentViewModel的构造函数中添加以下行
public ContentViewModel(IPersonService personService)
{
//GetPerson
Person.PropertyChanged +=person_PropertyChanged;
}并编写一个方法来处理调用CommandManager.InvalidateRequerySuggested()或SaveCommand.RaiseCanExecuteChanged()的事件
private void person_PropertyChanged(object sender, EventArgs args)
{
CommandManager.InvalidateRequerySuggested();
//SaveCommand.RaiseCanExecuteChanged()
}希望这能起作用。:-)
发布于 2012-03-11 18:09:25
简而言之,当你认为你的CanExecute()返回值可以改变的时候,你应该调用yourDelegateCommand.RaiseCanExecuteChanged()。
在您示例中,您应该通过INotifyPropertyChanged接口通知您的Person.Error属性已更改,订阅ContentViewModel类中的Person.PropertyChanged事件,并在每次更改Person.Error时调用SaveCommand.RaiseCanExecuteChanged()。请小心-在您的场景中,例如,当Person.FirstName发生更改时,Person.Error不会自动重新计算-您应该手动执行此操作。
更新:
public class ContentViewModel : ViewModelBase, IContentViewModel
{
public ContentViewModel(IPersonService personService)
{
Person = personService.GetPerson();
Person.PropertyChanged += Person_PropertyChanged;
SaveCommand = new DelegateCommand(Save, CanSave);
}
private void PersonPropertyChangedHandler(object sender, PropertyChangedEventArgs e)
{
SaveCommand.RaiseCanExecuteChanged();
}
private void Save()
{
// Save actions here...
}
private bool CanSave()
{
return IsErrorPresented(Person);
}
private bool IsErrorPresented(object o)
{
if (!(o is IDataErrorInfo))
return false;
var propNames = o.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Select(p => p.Name);
var o2 = (o as IDataErrorInfo);
var errors = propNames.Select(p => o2[p])
.Where(p => !String.IsNullOrEmpty(p))
.ToList();
ValidationSummary.ErrorMessages = errors;
return errors.Count > 0;
}
}
<TextBox Text="{Binding Person.FirstName,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
ValidatesOnExceptions=True,
NotifyOnValidationError=True}" />
<Button Content="Save" Command="{Binding SaveCommand}" />如果还将PropertyChanged指定为UpdateSourceTrigger,则在键入过程中将更新保存按钮。
https://stackoverflow.com/questions/9653874
复制相似问题