在多级 wpf 视图中验证子记录
假设我有一组这样的模型类:
public class Person
{
public string Name { get; set; }
public ObservableCollection<Job> Jobs { get; private set; }
}
public class Job
{
public string Title { get; set; }
public DateTime? Start { get; set; }
public DateTime? End { get; set; }
}
我像这样设置我的 xaml 以在单个视图上显示人员列表和所有详细信息:
<StackPanel Orientation="Horizontal">
<ListView ItemsSource="{Binding}" Width="200" DisplayMemberPath="Name" IsSynchronizedWithCurrentItem="True" />
<DockPanel Width="200" Margin="10,0">
<TextBox Text="{Binding Name}" DockPanel.Dock="Top" Margin="0,0,0,10"/>
<ListView ItemsSource="{Binding Jobs}" Name="_jobList" DisplayMemberPath="Title" IsSynchronizedWithCurrentItem="True"/>
</DockPanel>
<StackPanel Width="200" DataContext="{Binding ElementName=_jobList, Path=SelectedItem}">
<TextBox Text="{Binding Title}"/>
<DatePicker SelectedDate="{Binding Start}"/>
<DatePicker SelectedDate="{Binding End}"/>
</StackPanel>
</StackPanel>
整个窗口的 DataContext 是人员的 ObservbleCollection。这似乎运作得相当好。我现在想添加一些验证,但我不知道从哪里开始。
我想验证“职位”字段,以便在标题为空或同一个人中的职位重复或日期不按顺序时用户无法选择其他职位(或人员)。此外,如果名称为空,则无法更改人员。
我读过一些有关 WPF 中的验证的内容,但没有找到针对此场景的任何明确的解决方案。做这样的事情的最佳实践是什么?
另外,我的绑定是否可以像我在最后一个面板上设置 DataContext 的方式一样?它可以工作,但感觉有点粗略。另一种方法是为 CollectionDataSources 声明资源,但我也无法真正轻松地弄清楚该方法。
Lets say I have a set of model classes like this:
public class Person
{
public string Name { get; set; }
public ObservableCollection<Job> Jobs { get; private set; }
}
public class Job
{
public string Title { get; set; }
public DateTime? Start { get; set; }
public DateTime? End { get; set; }
}
I set up my xaml like this to display a list of people and all details on a single view:
<StackPanel Orientation="Horizontal">
<ListView ItemsSource="{Binding}" Width="200" DisplayMemberPath="Name" IsSynchronizedWithCurrentItem="True" />
<DockPanel Width="200" Margin="10,0">
<TextBox Text="{Binding Name}" DockPanel.Dock="Top" Margin="0,0,0,10"/>
<ListView ItemsSource="{Binding Jobs}" Name="_jobList" DisplayMemberPath="Title" IsSynchronizedWithCurrentItem="True"/>
</DockPanel>
<StackPanel Width="200" DataContext="{Binding ElementName=_jobList, Path=SelectedItem}">
<TextBox Text="{Binding Title}"/>
<DatePicker SelectedDate="{Binding Start}"/>
<DatePicker SelectedDate="{Binding End}"/>
</StackPanel>
</StackPanel>
The DataContext for the entire Window is an ObservbleCollection of People. This seems to work fairly well. I would now like to add some validation and I have no idea where to start.
I would like to validate the Job fields so that the user cannot select another Job (or person) if the title is empty or a duplicate within the same person, or if the dates are out of order. Additionally, the Person cannot be changed if the name is empty.
I have read a bit about validation in WPF, but have not found any clear solution for this scenario. What is the best practice for doing something like this?
Also, is my binding ok the way I set the DataContext on the last panel like that? It works, but it feels a little sketchy. The alternative is declaring resources for the CollectionDataSources and I couldn't really figure that method out very easily either.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对于验证部分,您可以从这里开始: http ://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/
理解本文后,您可以修改您的类 像这样:
例如,让我们为职位名称和职位开始日期添加一个非空职位验证:
Job class:
//////////假设我们为您的 xaml 代码使用了一个名为 MainWindow 的窗口,它看起来像这样
MainWindow.xaml
////////MainWindow.xaml.cs
/////////////////////////
一种简单的解决方案是,如果表单有错误,则禁用列表框(这就是我在上面的代码中所做的),并在没有错误时启用它们。另外,您可能应该在它们上放置一个漂亮的红色边框和工具提示,向用户解释为什么他不能再选择。
为了验证同一个人的头衔是否重复,您可以扩展上面的验证机制,使用一个 ValidationService 类来接收一个 Person,并查看拥有该职位的人是否还有另一个同名的职位。
公共类人:IDataErrorInfo
{
这不符合 MVVM 精神,如果您正在做的不仅仅是一个小型测试项目,您应该尝试学习 MVVM(您可以从这里开始:
那么您不会直接绑定到人员列表,而是会绑定一些 MainWindowViewModel 类。这个 MainWindowViewModel 类将包含人员列表,您将绑定到该列表。
对于选择,您的 MainWindowViewModel 中将有一个 CurrentJob 属性,即当前选定的作业,您将绑定到它:
基本上是这样的:
和您的 MainWindowViewModel:
For the validation part you can start here: http://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/
After you understand the article you could modify your classes like this:
For example let's add a non-empty title validation for job title and job start date:
Job class:
//////////Supposing we used a window called MainWindow for you xaml code it would look like
MainWindow.xaml
////////MainWindow.xaml.cs
//////////////////////
One simple solution is to disable the listboxes if the forms has errors (that's what I did in the code above), and enable them when there are no errors. Also you should probably put a nice red border with tooltip on them, explaining the user why he can't select anymore.
For validating if the title is duplicate within the same person, you could extend the validation mechanism above to have a ValidationService class that receives a Person and looks if the person who has the job also has another one with the same name.
public class Person: IDataErrorInfo
{
It's not in the MVVM spirit, and if what you're doing is going to be something more than a small test project you should try learn MVVM (You could start here: http://fernandomachadopirizen.wordpress.com/2010/06/10/a-simple-introduction-to-the-model-view-viewmodel-pattern-for-building-silverlight-and-windows-presentation-foundation-applications/)
Then you would not bind to a list of persons directly but instead you would have some MainWindowViewModel class to which you bind. This MainWindowViewModel class would contain the list of persons and you would bind to that.
And for the selection you would have a CurrentJob property in your MainWindowViewModel, that is the currently selected job, and you would bind to that:
Basically something like this:
And your MainWindowViewModel: