C# 主细节验证WPF
我有一个带有主细节视图的项目,其中主部分由一个选择对象的列表组成,细节部分显示该对象的细节并允许对其进行编辑 我的问题是,我不能允许两个对象具有相同的名称,虽然这听起来像是一项简单的任务,但我知道的验证过程并没有很好地发挥作用 下面是一个简短的例子 XAMLC# 主细节验证WPF,c#,wpf,xaml,master-detail,C#,Wpf,Xaml,Master Detail,我有一个带有主细节视图的项目,其中主部分由一个选择对象的列表组成,细节部分显示该对象的细节并允许对其进行编辑 我的问题是,我不能允许两个对象具有相同的名称,虽然这听起来像是一项简单的任务,但我知道的验证过程并没有很好地发挥作用 下面是一个简短的例子 XAML <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:WpfApplication1="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<ListView Grid.Column="0" ItemsSource="{Binding Path=People, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" Name="masterList"
DisplayMemberPath="Name" SelectedItem="{Binding Path=SelectedPerson}" />
<StackPanel Grid.Column="1" Margin="5" DataContext="{Binding Path=SelectedPerson}">
<TextBlock>Name</TextBlock>
<TextBox>
<TextBox.Text>
<Binding Path="Name" Mode="TwoWay" ValidatesOnDataErrors="True" NotifyOnValidationError="True">
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock>Address</TextBlock>
<TextBox Text="{Binding Path=Address}" />
<TextBlock>Phone</TextBlock>
<TextBox Text="{Binding Path=Phone}" />
</StackPanel>
</Grid>
</Window>
注册人员类别
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class Person {
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
public class RegisteredPeople {
public ObservableCollection<Person> People { get; set; }
public Person SelectedPerson { get; set; }
public RegisteredPeople() {
People = new ObservableCollection<Person>() {
new Person() {Name = "Ramzi", Address = "A1", Phone = "1"},
new Person() {Name = "Frank", Address = "A2", Phone = "12"},
new Person() {Name = "Ihab", Address = "A3", Phone = "123"}
};
}
}
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class Person : System.ComponentModel.IDataErrorInfo, INotifyPropertyChanged {
private string m_name;
public string Name {
get { return m_name; }
set {
m_name = value;
OnPropertyChanged();
OnPropertyChanged("People"); //Name of the list that the master list is bound to.
}
}
public string Address { get; set; }
public string Phone { get; set; }
public string this[string columnName] {
get {
switch (columnName) {
case "Name":
if (string.IsNullOrEmpty(Name)) {
/** This one works, but from here I cannot compare with names of other Person objects. **/
return "The name cannot be empty.";
}
break;
default:
return string.Empty;
}
return String.Empty;
}
}
public string Error { get; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class RegisteredPeople : System.ComponentModel.IDataErrorInfo {
public ObservableCollection<Person> People { get; set; }
public Person SelectedPerson { get; set; }
public RegisteredPeople() {
People = new ObservableCollection<Person>() {
new Person() {Name = "Ramzi", Address = "A1", Phone = "1"},
new Person() {Name = "Frank", Address = "A2", Phone = "12"},
new Person() {Name = "Ihab", Address = "A3", Phone = "123"}
};
}
public string this[string columnName] {
get {
switch (columnName) {
case "People":
foreach (Person person1 in People) {
foreach (Person person2 in People) {
if (person1 == person2) {
continue;
}
if (person1.Name == person2.Name) {
return "Error, 2 people cannot have the same name.";
}
}
}
break;
default:
return string.Empty;
}
return string.Empty;
}
}
public string Error { get; }
}
RegisteredPeople类的其他实现
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class Person {
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
public class RegisteredPeople {
public ObservableCollection<Person> People { get; set; }
public Person SelectedPerson { get; set; }
public RegisteredPeople() {
People = new ObservableCollection<Person>() {
new Person() {Name = "Ramzi", Address = "A1", Phone = "1"},
new Person() {Name = "Frank", Address = "A2", Phone = "12"},
new Person() {Name = "Ihab", Address = "A3", Phone = "123"}
};
}
}
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class Person : System.ComponentModel.IDataErrorInfo, INotifyPropertyChanged {
private string m_name;
public string Name {
get { return m_name; }
set {
m_name = value;
OnPropertyChanged();
OnPropertyChanged("People"); //Name of the list that the master list is bound to.
}
}
public string Address { get; set; }
public string Phone { get; set; }
public string this[string columnName] {
get {
switch (columnName) {
case "Name":
if (string.IsNullOrEmpty(Name)) {
/** This one works, but from here I cannot compare with names of other Person objects. **/
return "The name cannot be empty.";
}
break;
default:
return string.Empty;
}
return String.Empty;
}
}
public string Error { get; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class RegisteredPeople : System.ComponentModel.IDataErrorInfo {
public ObservableCollection<Person> People { get; set; }
public Person SelectedPerson { get; set; }
public RegisteredPeople() {
People = new ObservableCollection<Person>() {
new Person() {Name = "Ramzi", Address = "A1", Phone = "1"},
new Person() {Name = "Frank", Address = "A2", Phone = "12"},
new Person() {Name = "Ihab", Address = "A3", Phone = "123"}
};
}
public string this[string columnName] {
get {
switch (columnName) {
case "People":
foreach (Person person1 in People) {
foreach (Person person2 in People) {
if (person1 == person2) {
continue;
}
if (person1.Name == person2.Name) {
return "Error, 2 people cannot have the same name.";
}
}
}
break;
default:
return string.Empty;
}
return string.Empty;
}
}
public string Error { get; }
}
EventNameValidationRule
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows.Controls;
class EventNameValidationRule : ValidationRule {
public ObservableCollection<Person> EventList { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo) {
return new ValidationResult(false, "Duplicate names are not allowd.");
}
}
使用System.Collections.ObjectModel;
利用制度全球化;
使用System.Windows.Controls;
类EventNameValidationRule:ValidationRule{
公共ObservableCollection事件列表{get;set;}
公共覆盖验证结果验证(对象值,CultureInfo CultureInfo){
返回新的ValidationResult(false,“不允许重复名称”);
}
}
事情是这样抛出一个异常,表示绑定到EventList
是不好的。(没有这个列表,我显然没有比较的起点。)
我的问题:当有两个人叫同一个名字时,我如何将这个名字标记为无效?您需要在
Person
类中实现您的验证逻辑,即实现IDataErrorInfo
接口的实际DataContext
例如,您可以在RegisteredPeople
类中创建一个方法,从Person
类的索引器调用该方法,例如:
public class Person : IDataErrorInfo, INotifyPropertyChanged
{
private readonly IValidator _validator;
public Person(IValidator validator)
{
_validator = validator;
}
private string m_name;
public string Name
{
get { return m_name; }
set
{
m_name = value;
OnPropertyChanged();
}
}
public string Address { get; set; }
public string Phone { get; set; }
public string this[string columnName]
{
get
{
switch (columnName)
{
case "Name":
if (string.IsNullOrEmpty(Name))
{
/** This one works, but from here I cannot compare with names of other Person objects. **/
return "The name cannot be empty.";
}
else
{
return _validator.Validate(this);
}
default:
return string.Empty;
}
}
}
public string Error { get; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public interface IValidator
{
string Validate(Person person);
}
public class RegisteredPeople : IValidator
{
public ObservableCollection<Person> People { get; set; }
public Person SelectedPerson { get; set; }
public string Validate(Person person)
{
if (person != null && People.Any(x => x != person && x.Name == person.Name))
return "Same name!";
return null;
}
public RegisteredPeople()
{
People = new ObservableCollection<Person>() {
new Person(this) {Name = "Ramzi", Address = "A1", Phone = "1"},
new Person(this) {Name = "Frank", Address = "A2", Phone = "12"},
new Person(this) {Name = "Ihab", Address = "A3", Phone = "123"}
};
}
}
公共类人员:IDataErrorInfo,INotifyPropertyChanged
{
专用只读IValidator_验证程序;
公众人士(IValidator验证器)
{
_验证器=验证器;
}
私有字符串m_name;
公共字符串名
{
获取{return m_name;}
设置
{
m_name=值;
OnPropertyChanged();
}
}
公共字符串地址{get;set;}
公用字符串电话{get;set;}
公共字符串此[string columnName]
{
得到
{
开关(列名称)
{
案例“名称”:
if(string.IsNullOrEmpty(Name))
{
/**这一个可行,但从这里我无法与其他Person对象的名称进行比较**/
return“名称不能为空。”;
}
其他的
{
返回_validator.Validate(此);
}
违约:
返回字符串。空;
}
}
}
公共字符串错误{get;}
公共事件属性更改事件处理程序属性更改;
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共接口IValidator
{
字符串验证(个人);
}
公共类注册人:IValidator
{
公共可观察集合人员{get;set;}
公共人物SelectedPerson{get;set;}
公共字符串验证(个人)
{
if(person!=null&&People.Any(x=>x!=person&&x.Name==person.Name))
返回“同名!”;
返回null;
}
公共注册人员()
{
人员=新的可观察集合(){
新人(这个){Name=“Ramzi”,Address=“A1”,Phone=“1”},
新人(本){Name=“Frank”,Address=“A2”,Phone=“12”},
新人(本){Name=“Ihab”,Address=“A3”,Phone=“123”}
};
}
}
您需要在Person
类中实现验证逻辑,即实现IDataErrorInfo
接口的实际DataContext
例如,您可以在RegisteredPeople
类中创建一个方法,从Person
类的索引器调用该方法,例如:
public class Person : IDataErrorInfo, INotifyPropertyChanged
{
private readonly IValidator _validator;
public Person(IValidator validator)
{
_validator = validator;
}
private string m_name;
public string Name
{
get { return m_name; }
set
{
m_name = value;
OnPropertyChanged();
}
}
public string Address { get; set; }
public string Phone { get; set; }
public string this[string columnName]
{
get
{
switch (columnName)
{
case "Name":
if (string.IsNullOrEmpty(Name))
{
/** This one works, but from here I cannot compare with names of other Person objects. **/
return "The name cannot be empty.";
}
else
{
return _validator.Validate(this);
}
default:
return string.Empty;
}
}
}
public string Error { get; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public interface IValidator
{
string Validate(Person person);
}
public class RegisteredPeople : IValidator
{
public ObservableCollection<Person> People { get; set; }
public Person SelectedPerson { get; set; }
public string Validate(Person person)
{
if (person != null && People.Any(x => x != person && x.Name == person.Name))
return "Same name!";
return null;
}
public RegisteredPeople()
{
People = new ObservableCollection<Person>() {
new Person(this) {Name = "Ramzi", Address = "A1", Phone = "1"},
new Person(this) {Name = "Frank", Address = "A2", Phone = "12"},
new Person(this) {Name = "Ihab", Address = "A3", Phone = "123"}
};
}
}
公共类人员:IDataErrorInfo,INotifyPropertyChanged
{
专用只读IValidator_验证程序;
公众人士(IValidator验证器)
{
_验证器=验证器;
}
私有字符串m_name;
公共字符串名
{
获取{return m_name;}
设置
{
m_name=值;
OnPropertyChanged();
}
}
公共字符串地址{get;set;}
公用字符串电话{get;set;}
公共字符串此[string columnName]
{
得到
{
开关(列名称)
{
案例“名称”:
if(string.IsNullOrEmpty(Name))
{
/**这一个可行,但从这里我无法与其他Person对象的名称进行比较**/
return“名称不能为空。”;
}
其他的
{
返回_validator.Validate(此);
}
违约:
返回字符串。空;
}
}
}
公共字符串错误{get;}
公共事件属性更改事件处理程序属性更改;
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共接口IValidator
{
字符串验证(个人);
}
公共类注册人:IValidator
{
公共可观察集合人员{get;set;}
公共人物SelectedPerson{get;set;}
公共字符串验证(个人)
{
if(person!=null&&People.Any(x=>x!=person&&x.Name==person.Name))
返回“同名!”;
返回null;
}
公共注册人员()
{
人=新O