1

我无法使用 VS2012 for Windows Phone 让它工作。如果我使用属性 ValidateOnExceptions=true 创建一个文本框并在设置器中抛出异常,则不会捕获异常,而只会在调试窗口中出现:

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 时,这应该提供视觉反馈似乎非常明确:

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

4

1 回答 1

0

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>
于 2013-09-22T07:16:10.340 回答