【发布时间】:2011-12-14 00:23:34
【问题描述】:
我有一堂课如下:
public class Guardian : ModelBase, IDataErrorInfo
{
internal Guardian()
{
}
[Required]
[StringLength(50)]
[Display(Name = "Guardian's First Name")]
public string FirstName
{
get { return GetValue(() => FirstName); }
set { SetValue(() => FirstName, value); }
}
[Required]
[StringLength(50)]
[Display(Name = "Guardian's Last Name")]
public string LastName
{
get { return GetValue(() => LastName); }
set { SetValue(() => LastName, value); }
}
[USPhoneNumber]
[Display(Name = "Home Phone Number")]
public string HomePhone
{
get { return GetValue(() => HomePhone); }
set { SetValue(() => HomePhone, value.NormalizeNANPPhoneNumber()); }
}
[USPhoneNumber]
[Display(Name = "Personal Cell")]
public string PersonalCell
{
get { return GetValue(() => PersonalCell); }
set { SetValue(() => PersonalCell, value.NormalizeNANPPhoneNumber()); }
}
[Required]
[StringLength(100)]
[Display(Name = "Address")]
public string Address1
{
get { return GetValue(() => Address1); }
set { SetValue(() => Address1, value); }
}
[StringLength(100)]
public string Address2
{
get { return GetValue(() => Address2); }
set { SetValue(() => Address2, value); }
}
[Required]
[StringLength(100)]
public string City
{
get { return GetValue(() => City); }
set { SetValue(() => City, value); }
}
[Required]
[StringLength(100)]
public string State
{
get { return GetValue(() => State); }
set { SetValue(() => State, value); }
}
[Required]
[StringLength(20)]
[USPostalCode]
[Display(Name = "ZIP Code")]
public string Zip
{
get { return GetValue(() => Zip); }
set { SetValue(() => Zip, value); }
}
[Required]
[Display(Name = "Relationship to Children")]
public FamilyRole Relationship
{
get { return GetValue(() => Relationship); }
set { SetValue(() => Relationship, value); }
}
internal bool IsEmpty()
{
return
string.IsNullOrWhiteSpace(FirstName)
&& string.IsNullOrWhiteSpace(LastName)
&& string.IsNullOrWhiteSpace(HomePhone)
&& string.IsNullOrWhiteSpace(PersonalCell)
&& string.IsNullOrWhiteSpace(Address1)
&& string.IsNullOrWhiteSpace(Address2)
&& string.IsNullOrWhiteSpace(City)
&& string.IsNullOrWhiteSpace(State)
&& string.IsNullOrWhiteSpace(Zip)
&& Relationship == null
;
}
/// <summary>
/// Provides support for cross-cutting concerns without having to write
/// an attribute in Silverlight.
/// When time allows, convert to an Attribute. The code produced then
/// can be reused in other projects.
/// </summary>
/// <param name="listToAddTo"></param>
private void CustomValidation(List<ValidationResult> listToAddTo)
{
if (listToAddTo == null)
throw new ArgumentNullException("listToAddTo");
if (string.IsNullOrWhiteSpace(HomePhone) && string.IsNullOrWhiteSpace(PersonalCell))
listToAddTo.Add(new ValidationResult("At least one phone number must be filled in.", new string[] { "HomePhone" }));
}
#region IDataErrorInfo Members
public string Error
{
get
{
List<ValidationResult> results = new List<ValidationResult>();
this.IsValidObject(results);
CustomValidation(results);
if (results.Count > 0)
return results[0].ErrorMessage;
else
return null;
}
}
public string this[string columnName]
{
get
{
List<ValidationResult> results = new List<ValidationResult>();
this.IsValidObject(results);
CustomValidation(results);
var resultByColumn = results.Where(r => r.MemberNames.Contains(columnName)).ToList();
if (resultByColumn.Count > 0)
return resultByColumn[0].ErrorMessage;
else
return null;
}
}
#endregion
}
我为这个类实现了 IDataErrorInfo。一切正常,我的问题真的很烦人,但一个大到足以支付账单的人说需要解决。我有一个单独的 void 进行额外的验证,由 IDataErrorInfo 成员调用。它会检查是否填写了至少一个电话号码。
这个类的一个实例在我的模型上,称为 CurrentGuardian,该模型是以下弹出窗口的 DataContext:
<controls:ChildWindow xmlns:my="clr-namespace:Microsoft.Windows.Controls"
x:Class="Tracktion.Controls.CheckInWindows.AddGuardian"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
Width="575" Height="326"
Title="Add Parent/Guardian" HasCloseButton="False"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<controls:ChildWindow.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="12" />
</Style>
</controls:ChildWindow.Resources>
<Grid x:Name="LayoutRoot" Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="44" />
<RowDefinition Height="215*" />
<RowDefinition Height="45" />
</Grid.RowDefinitions>
<TextBlock Height="23" Name="textBlock1" Text="Please fill out the form below. Fields marked with an asterisk are required." VerticalAlignment="Top" TextAlignment="Center" />
<TextBlock Height="23" Margin="0,21,0,0" Name="textBlock2" Text="When done, click Add Another Guardian or Continue Adding Children below." VerticalAlignment="Top" TextAlignment="Center" />
<sdk:Label Grid.Row="1" Height="22" HorizontalAlignment="Left" Margin="0,11,0,0" Name="label1" VerticalAlignment="Top" Width="142" Content="* Guardian's First Name:" />
<sdk:Label Content="* Guardian's Last Name:" Height="22" HorizontalAlignment="Left" Margin="0,46,0,0" Name="label2" VerticalAlignment="Top" Width="142" Grid.Row="1" />
<sdk:Label Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="0,81,0,0" Name="label3" VerticalAlignment="Top" Width="142" Content="* Home Phone:" />
<sdk:Label Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="0,116,0,0" Name="label4" VerticalAlignment="Top" Width="120" Content="* Personal Cell:" />
<sdk:Label Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="302,11,0,0" Name="label5" VerticalAlignment="Top" Width="76" Content="* Address:" />
<sdk:Label Content="* What is your relationship to the child or children?" Height="23" HorizontalAlignment="Left" Margin="0,155,0,0" Name="label6" VerticalAlignment="Top" Width="360" Grid.Row="1" />
<TextBox Text="{Binding Path=CurrentGuardian.FirstName, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="148,5,0,0" Name="textBox1" VerticalAlignment="Top" Width="135" />
<TextBox Text="{Binding Path=CurrentGuardian.LastName, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="148,40,0,0" Name="textBox2" VerticalAlignment="Top" Width="135" />
<TextBox Text="{Binding Path=CurrentGuardian.HomePhone, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="148,75,0,0" Name="txtHomePhone" VerticalAlignment="Top" Width="135" LostFocus="PhoneNumber_LostFocus" />
<TextBox Text="{Binding Path=CurrentGuardian.PersonalCell, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="148,110,0,0" Name="txtCellPhone" VerticalAlignment="Top" Width="135" LostFocus="PhoneNumber_LostFocus" />
<my:WatermarkedTextBox Text="{Binding Path=CurrentGuardian.Address1, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="366,5,0,0" x:Name="textBox5" VerticalAlignment="Top" Width="184" Watermark="Line 1" />
<my:WatermarkedTextBox Text="{Binding Path=CurrentGuardian.Address2, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="366,40,0,0" x:Name="textBox6" VerticalAlignment="Top" Width="184" Watermark="Line 2" />
<my:WatermarkedTextBox Text="{Binding Path=CurrentGuardian.City, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="366,75,0,0" x:Name="textBox7" VerticalAlignment="Top" Width="184" Watermark="City" />
<ComboBox ItemsSource="{Binding Path=States}" DisplayMemberPath="Abbreviation" SelectedValuePath="Abbreviation" SelectedValue="{Binding Path=CurrentGuardian.State, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="366,110,0,0" Name="comboBox1" VerticalAlignment="Top" Width="88" />
<my:WatermarkedTextBox Text="{Binding Path=CurrentGuardian.Zip, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="460,110,0,0" x:Name="textBox8" VerticalAlignment="Top" Width="90" Watermark="ZIP" />
<ComboBox DisplayMemberPath="Name" Height="28" HorizontalAlignment="Left" ItemsSource="{Binding Path=Relationships}" Margin="302,149,0,0" Name="comboBox2" SelectedItem="{Binding Path=CurrentGuardian.Relationship, Mode=TwoWay, ValidatesOnDataErrors=True}" VerticalAlignment="Top" Width="249" Grid.Row="1" />
<Button Content="Cancel" Grid.Row="2" Height="37" HorizontalAlignment="Left" Margin="0,8,0,0" Name="btnCancel" VerticalAlignment="Top" Width="93" Style="{StaticResource RedButton}" Click="btnCancel_Click" />
<StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Right">
<Button Content="Add Another Guardian" Height="37" Margin="5,8,0,0" Name="btnAddGuardian" VerticalAlignment="Top" Style="{StaticResource OrangeButton}" HorizontalAlignment="Right" Width="159" Click="btnAddGuardian_Click" />
<Button Content="Continue" Height="37" Margin="5,8,0,0" Name="btnContinue" VerticalAlignment="Top" Style="{StaticResource GreenButton}" HorizontalAlignment="Right" Padding="20,0" Click="btnContinue_Click" />
<!-- TODO: Visibility set when accessing this screen through check in screen. -->
<Button Content="Check In" Margin="5,8,0,0" Name="btnCheckIn" Visibility="Collapsed" Style="{StaticResource GreenButton}" Click="btnCheckIn_Click" />
</StackPanel>
</Grid>
需要一个电话号码。您可以输入两者,但至少需要输入一个。当表单绑定到空的 CurrentGuardian 时,第一个电话号码字段 Home Phone 以红色突出显示。当两个数字都没有数据时,在聚焦和模糊该字段后,它会保持红色。如果我输入电话号码,该字段将变为黑色。删除数字会将其变为红色。到目前为止,一切都很好 - 这是预期的行为。现在,如果我没有为家庭电话输入一个号码,但是我为个人手机输入了一个电话号码,当我关闭个人手机时,家庭电话号码会一直以红色突出显示,直到我点击它。一旦我点击它,红色轮廓就会消失。如何使字段验证?我目前在两个字段的模糊事件中都有以下代码:
private void PhoneNumber_LostFocus(object sender, RoutedEventArgs e)
{
KioskCheckIn2 model = (KioskCheckIn2)this.DataContext;
model.CurrentGuardian.IsValidObject(); // revalidate
txtHomePhone.GetBindingExpression(TextBox.TextProperty).UpdateSource();
txtCellPhone.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}
我有 ValidationResult 用于检查两个数字,只返回 HomePhone 字段作为违规控件,因为我无法弄清楚如何强制重新验证控件,因此两个红色轮廓都会消失。
提前致谢!
【问题讨论】:
标签: silverlight validation xaml