WPF DataGrid 绑定验证和转换问题
我想知道 DataGrid 绑定对于不同类型的错误有何不同的行为。 我已经设置了一个示例项目:
数据类:
public class MajorEvent : INotifyPropertyChanged, IDataErrorInfo
{
private DateTime when;
public DateTime When
{
get { return when; }
set
{
if (value > DateTime.Now)
{
throw new ArgumentOutOfRangeException("value", "A Major event can't happen in the future!");
}
when = value;
}
}
public string What { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public string this[string columnName]
{
get
{
if (columnName.Equals("What"))
{
if (string.IsNullOrEmpty(What))
{
return "An event needs an agenda!";
}
}
return string.Empty;
}
}
public string Error
{
get { return null; }
}
}
主窗口代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
dg.ItemsSource = new ObservableCollection<MajorEvent>
{
new MajorEvent {What = "Millenium celebrations", When = new DateTime(1999, 12, 31)},
new MajorEvent {What = "I Have A Dream Speach", When = new DateTime(1963, 8, 28)},
new MajorEvent {What = "First iPhone Release", When = new DateTime(2007, 6, 29)},
new MajorEvent {What = "My Birthday", When = new DateTime(1983, 5, 13)},
new MajorEvent {What = "Friends Backstabbing Day", When = new DateTime(2009, 6, 8)},
};
}
}
和 MainWindow Xaml:
<Window x:Class="DataGridValidationIssue.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid x:Name="dg" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="What" Binding="{Binding What, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Width="*"/>
<DataGridTextColumn Header="When" Binding="{Binding When, StringFormat='d', ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Width="Auto"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
现在,关于日期列 - 当我输入未来日期(从而导致 ArgumentOutOfRangeException)时,文本列仍然可以编辑。当我提供无效日期(例如 5 月 35 日)时,则无法编辑文本列。
为什么 WPF 会有这样的行为?
I was wondering how does the DataGrid Binding behaves differently for different kind of errors.
I've set up a sample project:
The Data Class:
public class MajorEvent : INotifyPropertyChanged, IDataErrorInfo
{
private DateTime when;
public DateTime When
{
get { return when; }
set
{
if (value > DateTime.Now)
{
throw new ArgumentOutOfRangeException("value", "A Major event can't happen in the future!");
}
when = value;
}
}
public string What { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public string this[string columnName]
{
get
{
if (columnName.Equals("What"))
{
if (string.IsNullOrEmpty(What))
{
return "An event needs an agenda!";
}
}
return string.Empty;
}
}
public string Error
{
get { return null; }
}
}
Main Window Code Behind :
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
dg.ItemsSource = new ObservableCollection<MajorEvent>
{
new MajorEvent {What = "Millenium celebrations", When = new DateTime(1999, 12, 31)},
new MajorEvent {What = "I Have A Dream Speach", When = new DateTime(1963, 8, 28)},
new MajorEvent {What = "First iPhone Release", When = new DateTime(2007, 6, 29)},
new MajorEvent {What = "My Birthday", When = new DateTime(1983, 5, 13)},
new MajorEvent {What = "Friends Backstabbing Day", When = new DateTime(2009, 6, 8)},
};
}
}
and MainWindow Xaml:
<Window x:Class="DataGridValidationIssue.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid x:Name="dg" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="What" Binding="{Binding What, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Width="*"/>
<DataGridTextColumn Header="When" Binding="{Binding When, StringFormat='d', ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Width="Auto"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Now, regarding the date column - when I enter a future date (thus causing an ArgumentOutOfRangeException) the text column can still be edited. When I'm providing an invalid date (for example, May 35'th), then the text column can not be edited.
Why does WPF behave like this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
DateTime
范围内的默认验证行为是,当您输入无法转换为DateTime
的字符串时(即 5 月 35 日或其他奇特的事情),抛出异常。一旦抛出异常,TextBox
就会被阻止。在您的情况下,您没有检查
IDataErrorInfo
实现中的日期值! (如果需要,请在此处了解有关 IDataErrorInfo 的更多信息)抛出异常似乎是合乎逻辑的遵循默认的
DateTime
验证过程,因为您正在验证异常。您应该在this[string propertyName]
处理日期范围中添加一个案例(我认为您必须在此处为“When”属性添加一个案例,测试日期范围)Default validation behavior in a
DateTime
scope is to throw an Exception when you enter a String that cannot be converted into aDateTime
(ie May 35th or another fancy thing). Once the exception thrown, theTextBox
is blockedIn your case, you are not checking the Date value in your
IDataErrorInfo
implementation! ( more information about IDataErrorInfo here if needed )It seems logical that an exception is thrown following the default
DateTime
validation process, since you are validating on exceptions. You should add a case in yourthis[string propertName]
handling Date range (I think you have to add a case for the "When" property here, testing the date range)