简体   繁体   中英

WP8 - ValidatesOnExceptions

I can't get this to work using VS2012 for Windows Phone. If I create a text box with the property ValidateOnExceptions=true and throw an exception in the setter, the exception is not caught but just comes out in the debug window:

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().

I made a toy example to isolate the issue - here's my 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>

My main page:

/* 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();
    }

  }
}

I've scoured this for clues, but it seems pretty categorical that this SHOULD provide visual feedback when ValidateOnExceptions=true, and is supported for WP8:

http://msdn.microsoft.com/en-us/library/windowsphone/develop/cc278072(v=vs.105).aspx#BKMK_Datavalidation

Our program Terminator does validation of geo-coordinates using IErrorInfo and friends.

You'll probably find that the validation mechanism is working, but you'll need to add the correct styles to the Visual State Manager in the control template. Here's our validating textbox 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM