2017-08-16 5 views
2

Je suis en train d'écrire un ValidationRule qui vérifie si une chaîne est nulle:ValidationRule ValidatesOnTargetUpdated NullReferenceException au moment du design

public class NotNullValidationRule : ValidationRule 
{ 
    public override ValidationResult Validate(object value, CultureInfo cultureInfo) 
    { 
    string str = value as string; 

    return string.IsNullOrEmpty(str) ? new ValidationResult(false, Application.Current.FindResource("EmptyStringNotAllowed")) : ValidationResult.ValidResult; 
    } 
} 

Dans ma fenêtre je l'utilise comme ceci:

<TextBox 
    Name="TxtDescription" 
    Width="Auto" 
    controls:TextBoxHelper.Watermark="{DynamicResource Description}"> 
    <TextBox.Text> 
     <Binding Path="MachineToEdit.Description"> 
      <Binding.ValidationRules> 
       <validation:NotNullValidationRule ValidatesOnTargetUpdated="True"/> 
      </Binding.ValidationRules> 
     </Binding> 
    </TextBox.Text> 
</TextBox> 

Si je démarrer le concepteur Je reçois cette exception NullReferenceException:

at System.Windows.Data.BindingExpression.RunValidationRule(ValidationRule validationRule, Object value, CultureInfo culture) 
    at System.Windows.Data.BindingExpression.ValidateOnTargetUpdated() 
    at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange) 
    at System.Windows.Data.BindingExpression.Activate(Object item) 
    at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt) 
    at System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance) 
    at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance) 
    at MS.Internal.Data.DataBindEngine.Run(Object arg) 
    at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) 
    at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler) 
    at System.Windows.Threading.DispatcherOperation.InvokeImpl() 
    at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) 
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Windows.Threading.DispatcherOperation.Invoke() 
    at System.Windows.Threading.Dispatcher.ProcessQueue() 
    at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) 
    at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) 
    at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) 
    at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) 
    at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler) 
    at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) 
    at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) 
    at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) 
    at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) 
    at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) 
    at System.Windows.Application.RunDispatcher(Object ignore) 
    at System.Windows.Application.RunInternal(Window window) 
    at System.Windows.Application.Run(Window window) 
    at Microsoft.VisualStudio.DesignTools.DesignerContract.Isolation.DesignerProcess.RunApplication() 
    at Microsoft.VisualStudio.DesignTools.DesignerContract.Isolation.DesignerProcess.<>c__DisplayClass5_0.<Main>b__0() 
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ThreadHelper.ThreadStart() 

Pourquoi cela se produit-il? Si je n'active pas ValidatesOnTargetUpdated, cela fonctionne. Mais je dois valider quand la fenêtre se charge.

Merci pour toutes les réponses et bonne journée.

Répondre

0

Avertissement non testé!

Je suis d'avis que la valeur est null dans la méthode Validate in designtime. Donc, vous devriez vérifier si actuellement en conception, puis retourner quelque chose de valide comme ValidationResult.ValidResult.

public class NotNullValidationRule : ValidationRule 
{ 
    public override ValidationResult Validate(object value, CultureInfo cultureInfo) 
    { 

    if ((bool)(DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue)) 
    { 
     return ValidationResult.ValidResult; 
    } 

    string str = value as string; 

    return string.IsNullOrEmpty(str) ? new ValidationResult(false, Application.Current.FindResource("EmptyStringNotAllowed")) : ValidationResult.ValidResult; 
    } 
} 
0

EDIT: Une meilleure réponse que le code-behind

Dans VS2017, ce qui permet le code de projet dans l'éditeur XAML également fixé pour moi.

Enable Project Code Button

--- Réponse précédente ---

Je faisais la même question et la réponse de Thomas V n'a malheureusement pas marché. J'ai été en mesure de résoudre le problème en déplaçant l'ajout de ValidationRules à codebehind. Peut-être pas la méthode la plus idéale, mais elle a corrigé le problème.

Vous pourriez également envisager d'envelopper la logique de codebehind dans la vérification du concepteur de Thomas V, mais cela a fonctionné sans cela pour moi.

XAML:

<TextBox x:Name="FirstNameTextBox"> 
    <TextBox.Text> 
     <Binding x:Name="FirstNameTextBoxBinding" 
       Path="TheNewUser.TheNewUser.GivenName" 
       UpdateSourceTrigger="PropertyChanged" 
       Mode="TwoWay" 
       NotifyOnValidationError="True" 
       Delay="500" /> 
    </TextBox.Text> 
</TextBox> 

CodeBehind:

public NewUserWizard_Info_View() 
    { 
     InitializeComponent(); 

     Loaded += TriggerValidationOnLoaded; 

     FirstNameTextBoxBinding.ValidationRules.Add(new ValidateEmptyOrNull() 
     { 
      ValidatesOnTargetUpdated = true 
     });    
    } 

    private void TriggerValidationOnLoaded(object obj, RoutedEventArgs e) 
    { 
    // This is needed to trigger the validation on first load 
     FirstNameTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource(); 
    }