我无法使用VS2012 for Windows Phone实现此功能。如果我创建一个包含属性ValidateOnExceptions = true的文本框并在setter中抛出异常,则不会捕获异常但只是在调试窗口中出现:
A first chance exception of type 'System.ArgumentException' occurred in PhoneApp1.DLL
An exception of type 'System.ArgumentException' occurred in PhoneApp1.DLL but was not handled in user code
System.Windows.Data Error: Cannot save value from target back to source. BindingExpression: Path='Thingy' DataItem='PhoneApp1.MyContext' (HashCode=38891250); target element is 'System.Windows.Controls.TextBox' (Name=''); target property is 'Text' (type 'System.String').. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: I said don't type 'foo'!
at PhoneApp1.MyContext.set_Thingy(String value)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
at System.Windows.CLRPropertyListener.set_Value(Object value)
at System.Windows.PropertyAccessPathStep.set_Value(Object value)
at System.Windows.Data.BindingExpression.UpdateValue().
我做了一个玩具示例来隔离问题 - 这是我的xaml:
<phone:PhoneApplicationPage
x:Class="PhoneApp1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:my="clr-namespace:PhoneApp1;assembly=PhoneApp1"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="Do NOT type 'foo' in this box"/>
<TextBox Text="{Binding Thingy, Mode=TwoWay, ValidatesOnExceptions=True}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
</Grid>
</Grid>
</phone:PhoneApplicationPage>
我的主页:
/* imports snipped..*/
namespace PhoneApp1 {
public class MyContext {
private String _thingy = String.Empty;
public String Thingy {
get {
return _thingy;
}
set {
if (value == "foo") {
throw new ArgumentException("I said don't type 'foo'!");
}
_thingy = value;
}
}
public MyContext() {
}
}
public partial class MainPage : PhoneApplicationPage {
// Constructor
public MainPage() {
InitializeComponent();
this.DataContext = new MyContext();
}
}
}
我已经搜索了这个线索,但是当ValidateOnExceptions = true并且WP8支持时,它应该提供视觉反馈,这似乎很明确:
答案 0 :(得分:0)
我们的程序Terminator使用IErrorInfo和朋友验证地理坐标。
您可能会发现验证机制正常,但您需要在控件模板中向Visual State Manager添加正确的样式。这是我们的验证文本框stye
<Style x:Key="ValidatingTextBox" TargetType="TextBox">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
<Setter Property="Background" Value="{StaticResource PhoneTextBoxBrush}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneTextBoxForegroundBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource PhoneTextBoxBrush}"/>
<Setter Property="SelectionBackground" Value="{StaticResource PhoneAccentBrush}"/>
<Setter Property="SelectionForeground" Value="{StaticResource PhoneTextBoxSelectionForegroundBrush}"/>
<Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ValidationStates">
<VisualState x:Name="Valid" >
<Storyboard Duration="00:00:01">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
Storyboard.TargetName="WarningEllipse">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
Storyboard.TargetName="WarningText">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="InvalidUnfocused">
<Storyboard Duration="00:00:01">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
Storyboard.TargetName="WarningEllipse">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<!-- note the warning text is not shown if unfocused -->
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
Storyboard.TargetName="WarningText">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="InvalidFocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
Storyboard.TargetName="WarningText">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
Storyboard.TargetName="WarningEllipse">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="EnabledBorder">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisabledOrReadonlyBorder">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ReadOnly">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="EnabledBorder">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisabledOrReadonlyBorder">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="DisabledOrReadonlyBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="DisabledOrReadonlyBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="DisabledOrReadonlyContent">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxReadOnlyBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="EnabledBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="EnabledBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneTextBoxEditBorderBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="EnabledBorder"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ContentControl Grid.Row="0" x:Name="ContentElement" BorderThickness="0" HorizontalContentAlignment="Stretch"
Margin="{StaticResource PhoneTextBoxInnerMargin}"
Padding="{TemplateBinding Padding}"
VerticalContentAlignment="Top"/>
<Ellipse Grid.Row="0"
x:Name="WarningEllipse" Visibility="Collapsed"
Margin="12,12,12,0"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Width="14" Height="14"
Stroke="#40000000" StrokeThickness="2" Fill="Red">
</Ellipse>
<TextBlock x:Name="WarningText" Grid.Row="1" Foreground="Red" Visibility="Collapsed" TextWrapping="Wrap"
Margin="3,-12,3,0"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(Validation.Errors)[0].ErrorContent, FallbackValue=''}"></TextBlock>
</Grid>
</Border>
<Border x:Name="DisabledOrReadonlyBorder" BorderBrush="{StaticResource PhoneDisabledBrush}"
BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent"
Margin="{StaticResource PhoneTouchTargetOverhang}" Visibility="Collapsed">
<TextBox x:Name="DisabledOrReadonlyContent"
Background="Transparent"
Foreground="{StaticResource PhoneDisabledBrush}"
FontWeight="{TemplateBinding FontWeight}" FontStyle="{TemplateBinding FontStyle}"
FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}"
IsReadOnly="True" SelectionForeground="{TemplateBinding SelectionForeground}"
SelectionBackground="{TemplateBinding SelectionBackground}" TextAlignment="{TemplateBinding TextAlignment}"
TextWrapping="{TemplateBinding TextWrapping}" Text="{TemplateBinding Text}"
Template="{StaticResource PhoneDisabledTextBoxTemplate}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>