WPF-MVVM 中的错误处理/禁用按钮
我在查看错误处理时遇到问题。我使用 caliburn.micro 和 MEF。
我的虚拟机看起来像这样:
[Export(typeof(IShellViewModel))]
public class ShellViewModel : PropertyChangedBase, IShellViewModel,IDataErrorInfo
{
#region Private members
private User _user;
private Dictionary<string, bool> _validProperties;
private bool _allPropertiesValid;
#endregion
#region Private methods
private void ValidateProperties()
{
if (_validProperties.Values.Any(isValid => !isValid))
{
AllPropertiesValid = false;
return;
}
AllPropertiesValid = true;
}
#endregion
#region Constructor
public ShellViewModel()
{
_user = new User();
_validProperties = new Dictionary<string, bool> {{"Nick", false}, {"Password", false}};
}
#endregion
#region Properties
public bool AllPropertiesValid
{
get { return _allPropertiesValid; }
set
{
if (_allPropertiesValid != value)
{
_allPropertiesValid = value;
NotifyOfPropertyChange("AllPropertiesValid");
}
}
}
#endregion
#region Implementation of IShellViewModel
public string Nick
{
get { return _user.Nick; }
set
{
_user.Nick = value;
NotifyOfPropertyChange("Nick");
}
}
public string Password
{
get { return _user.Password; }
set
{
_user.Password = value;
NotifyOfPropertyChange("Password");
}
}
public void EmptyLogOn()
{
MessageBox.Show(string.Format("LogOn on server with credential: {0}, {1}", Nick, Password));
}
public void LogOn(string nick, string password)
{
MessageBox.Show(string.Format("LogOn on server with credential: {0}, {1}", nick, password));
}
#endregion
#region Implementation of IDataErrorInfo
public string Error
{
get { return (_user as IDataErrorInfo).Error; }
}
public string this[string propertyName]
{
get
{
string error = (_user as IDataErrorInfo)[propertyName];
_validProperties[propertyName] = String.IsNullOrEmpty(error) ? true : false;
ValidateProperties();
CommandManager.InvalidateRequerySuggested();
return error;
}
}
#endregion
}
如果我有一些错误,我将属性 AllPropertiesValid 设置为 false。我将此属性绑定到 Button 属性 IsEnabled 上。
所以在视图中我有这个:
<Button IsEnabled="{Binding AllPropertiesValid, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Micro:Message.Attach="EmptyLogOn"
Content="Prihlás ma"
Width="100"
Height="25"
VerticalAlignment="Center"
Grid.Row="2"
Grid.ColumnSpan="2"></Button>
<Label Content="{Binding AllPropertiesValid}" Grid.Row="3"/>
但如果属性 AllPropertiesValid 为 false 按钮仍处于启用状态。我检查 AllPropertiesValid 的值(我将此属性绑定到标签上并且标签内容为 false)为 false。
怎么了 ?感谢您的提前。
编辑:在设计器中按钮被禁用,但加载窗口按钮时启用。
I have problem with error handling in view. I use caliburn.micro and MEF.
My VM look like this:
[Export(typeof(IShellViewModel))]
public class ShellViewModel : PropertyChangedBase, IShellViewModel,IDataErrorInfo
{
#region Private members
private User _user;
private Dictionary<string, bool> _validProperties;
private bool _allPropertiesValid;
#endregion
#region Private methods
private void ValidateProperties()
{
if (_validProperties.Values.Any(isValid => !isValid))
{
AllPropertiesValid = false;
return;
}
AllPropertiesValid = true;
}
#endregion
#region Constructor
public ShellViewModel()
{
_user = new User();
_validProperties = new Dictionary<string, bool> {{"Nick", false}, {"Password", false}};
}
#endregion
#region Properties
public bool AllPropertiesValid
{
get { return _allPropertiesValid; }
set
{
if (_allPropertiesValid != value)
{
_allPropertiesValid = value;
NotifyOfPropertyChange("AllPropertiesValid");
}
}
}
#endregion
#region Implementation of IShellViewModel
public string Nick
{
get { return _user.Nick; }
set
{
_user.Nick = value;
NotifyOfPropertyChange("Nick");
}
}
public string Password
{
get { return _user.Password; }
set
{
_user.Password = value;
NotifyOfPropertyChange("Password");
}
}
public void EmptyLogOn()
{
MessageBox.Show(string.Format("LogOn on server with credential: {0}, {1}", Nick, Password));
}
public void LogOn(string nick, string password)
{
MessageBox.Show(string.Format("LogOn on server with credential: {0}, {1}", nick, password));
}
#endregion
#region Implementation of IDataErrorInfo
public string Error
{
get { return (_user as IDataErrorInfo).Error; }
}
public string this[string propertyName]
{
get
{
string error = (_user as IDataErrorInfo)[propertyName];
_validProperties[propertyName] = String.IsNullOrEmpty(error) ? true : false;
ValidateProperties();
CommandManager.InvalidateRequerySuggested();
return error;
}
}
#endregion
}
If I have som error I set properties AllPropertiesValid on false. I bind this properties on Button properties IsEnabled.
So in View I have this:
<Button IsEnabled="{Binding AllPropertiesValid, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Micro:Message.Attach="EmptyLogOn"
Content="Prihlás ma"
Width="100"
Height="25"
VerticalAlignment="Center"
Grid.Row="2"
Grid.ColumnSpan="2"></Button>
<Label Content="{Binding AllPropertiesValid}" Grid.Row="3"/>
But if properties AllPropertiesValid is false Button is still enabled. I check the value of AllPropertiesValid (I bind this properties on label and label content is false) is false.
What’s wrong ? Thank for advance.
EDIT: In designer is button disabled, but when is loaded window button is enable.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您正在使用MVVM,那么您应该使用
ICommand
(或其他更高级别的变体,例如CommandBase
,...),因为您需要单击按钮时执行某些操作。在本例中,您绑定到 ViewModel 上的命令属性,在命令中的
CanExecute
上返回 false,并且按钮被禁用。有时您必须调用CommandManager.InvalidateRequerySuggested()
。这并不能解释为什么您的代码不起作用。老实说,我觉得还不错。
If you are doing MVVM then you should be using
ICommand
(or other higher-level variants such asCommandBase
, ...) since you need to do something when button is clicked.In this case you bind to a command property on the ViewModel, you return false on the
CanExecute
in the command and button is disabled. Sometimes you have to callCommandManager.InvalidateRequerySuggested()
.This does not explain why your code is not working. To be honest, it looks alright to me.