3

ユーザーが入力しているときにテキスト フィールドを検証したいと思います。最初はテキストは空です。検証規則は次のとおりです。 1 数値のみです。2 0 より大きく 5 より小さい。以下は xmal のコードです。

 <TextBox Grid.Column="1" HorizontalAlignment="Left" Style="{StaticResource textBoxInError}" Name="txtQuantity" Margin="70,0,0,0" Width="70">
   <TextBox.Text>
     <Binding RelativeSource="{RelativeSource Mode=Self}" Path="Text" UpdateSourceTrigger="PropertyChanged">
       <Binding.ValidationRules>                                            
         <ValidationRules:PositiveIntegerRule Min="1" Max="5"></ValidationRules:PositiveIntegerRule>
       </Binding.ValidationRules>
     </Binding>
   </TextBox.Text>
 </TextBox>

私の検証クラスは次のとおりです(中国語の文字は無視してください。エラーメッセージです):

 class PositiveIntegerRule : ValidationRule
{
    public ushort Max { get; set; }
    public ushort Min { get; set; }

    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
       ushort tmp = 0;
        try
        {
            if (value != null && !String.IsNullOrEmpty(value.ToString()))
            {
                tmp = ushort.Parse(value.ToString());
            }
            else
            {
                return new ValidationResult(false,"数值不能为空");
            }
        }
        catch (Exception e)
        {
            return new ValidationResult(false, "含有不合法字符");
        }

        if(tmp < Min || tmp > Max)
        {
            return new ValidationResult(false,string.Format("超出数值范围:最大值为{0},最小值为{1}",Max,Min));
        }
        else
        {
            return new ValidationResult(true,null);
        }
    }
}

問題は、有効な値を入力している限り、この wpf アプリケーションを実行すると、スタック オーバーフロー例外がスローされることです。メソッド ValidationResult が無限に呼び出されました。一方、無効な値を入力すると、ValidationResult メソッドは 1 回だけ呼び出されます。ただし、リソースで定義された無効化値のスタイルは適用されません。

この問題の原因は同時使用にあると思いますRelativeSource="{RelativeSource Mode=Self and UpdateSourceTrigger="PropertyChanged"。ソースと宛先は同じものを指しています。したがって、それらは互いに無限に更新されます。OneWayToSource に別のバインド モードを試してみましたが、まだ機能しません。

  1. RelativeSource="{RelativeSource Mode=Self}"と をUpdateSourceTrigger="PropertyChanged"一緒に使用すると実際に何が起こるか説明してくれる人はいますか?
  2. 有効な値が無限ループを引き起こす理由がわかりませんが、無効な値はそうではありません。メソッドが をValidate返した場合、 new ValidationResult(false,xxx).net フレームワーク内のどこかでプログラムの実行を停止する例外がスローされ、無限ループが発生しないためです。有効な値は反対にあります。
  3. call メソッドを保持するように Validate メソッドを呼び出し続けるのではなく、スタック オーバーフロー例外が発生した理由CanExecute

どうもありがとう

コールスタックを追加しました:

>   JieMeiTaoInventoryManager.exe!JieMeiTaoInventoryManager.ValidationRules.PositiveIntegerRule.Validate(object value, System.Globalization.CultureInfo cultureInfo) Line 16    C#
PresentationFramework.dll!System.Windows.Data.BindingExpressionBase.Validate(object value, System.Windows.Controls.ValidationStep validationStep) + 0x19a bytes 
PresentationFramework.dll!System.Windows.Data.BindingExpression.Validate(object value, System.Windows.Controls.ValidationStep validationStep) + 0x18 bytes  
PresentationFramework.dll!System.Windows.Data.BindingExpressionBase.UpdateValue() + 0x2e bytes  
PresentationFramework.dll!System.Windows.Data.BindingExpression.Update(bool synchronous) + 0x4f bytes   
PresentationFramework.dll!System.Windows.Data.BindingExpressionBase.Dirty() + 0x30 bytes    
PresentationFramework.dll!System.Windows.Data.BindingExpression.SetValue(System.Windows.DependencyObject d, System.Windows.DependencyProperty dp, object value) + 0x27 bytes    
WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal) + 0x3c7 bytes  
PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.SetValue(object item, object value) + 0x171 bytes 
PresentationFramework.dll!MS.Internal.Data.ClrBindingWorker.UpdateValue(object value) + 0xa3 bytes  
PresentationFramework.dll!System.Windows.Data.BindingExpression.UpdateSource(object value) + 0x99 bytes 
PresentationFramework.dll!System.Windows.Data.BindingExpressionBase.UpdateValue() + 0x66 bytes  
PresentationFramework.dll!System.Windows.Data.BindingExpression.Update(bool synchronous) + 0x4f bytes   
PresentationFramework.dll!System.Windows.Data.BindingExpressionBase.Dirty() + 0x30 bytes    
PresentationFramework.dll!System.Windows.Data.BindingExpression.SetValue(System.Windows.DependencyObject d, System.Windows.DependencyProperty dp, object value) + 0x27 bytes    
WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal) + 0x3c7 bytes  
WindowsBase.dll!System.Windows.DependencyObject.SetCurrentDeferredValue(System.Windows.DependencyProperty dp, System.Windows.DeferredReference deferredReference) + 0x29 bytes  
PresentationFramework.dll!System.Windows.Controls.TextBox.OnTextContainerChanged(object sender, System.Windows.Documents.TextContainerChangedEventArgs e) + 0xa7 bytes  
PresentationFramework.dll!System.Windows.Documents.TextContainer.EndChange(bool skipEvents) + 0xd9 bytes    
PresentationFramework.dll!System.Windows.Documents.TextContainer.System.Windows.Documents.ITextContainer.EndChange(bool skipEvents) + 0xb bytes 
PresentationFramework.dll!System.Windows.Documents.TextRangeBase.EndChange(System.Windows.Documents.ITextRange thisRange, bool disableScroll, bool skipEvents) + 0x77 bytes 
PresentationFramework.dll!System.Windows.Documents.TextRange.System.Windows.Documents.ITextRange.EndChange(bool disableScroll, bool skipEvents) + 0x15 bytes    
PresentationFramework.dll!System.Windows.Documents.TextRange.ChangeBlock.System.IDisposable.Dispose() + 0x15 bytes  
PresentationFramework.dll!System.Windows.Documents.TextEditorTyping.DoTextInput(System.Windows.Documents.TextEditor This, string textData, bool isInsertKeyToggled, bool acceptControlCharacters) + 0x1b2 bytes 
PresentationFramework.dll!System.Windows.Documents.TextEditorTyping.TextInputItem.Do() + 0x20 bytes 
PresentationFramework.dll!System.Windows.Documents.TextEditorTyping.ScheduleInput(System.Windows.Documents.TextEditor This, System.Windows.Documents.TextEditorTyping.InputItem item) + 0x2f bytes  
PresentationFramework.dll!System.Windows.Documents.TextEditorTyping.OnTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e) + 0x16c bytes   
PresentationFramework.dll!System.Windows.Controls.Primitives.TextBoxBase.OnTextInput(System.Windows.Input.TextCompositionEventArgs e) + 0x35 bytes  
PresentationCore.dll!System.Windows.UIElement.OnTextInputThunk(object sender, System.Windows.Input.TextCompositionEventArgs e) + 0x6f bytes 
PresentationCore.dll!System.Windows.Input.TextCompositionEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) + 0x31 bytes    
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) + 0x29 bytes  
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) + 0x3e bytes    
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) + 0xbe bytes   
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) + 0x79 bytes  
PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args) + 0x41 bytes   
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) + 0x2c bytes    
PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() + 0x1ff bytes   
PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) + 0x45 bytes 
PresentationCore.dll!System.Windows.Input.TextCompositionManager.UnsafeCompleteComposition(System.Windows.Input.TextComposition composition) + 0x7e bytes   
PresentationCore.dll!System.Windows.Input.TextCompositionManager.PostProcessInput(object sender, System.Windows.Input.ProcessInputEventArgs e) + 0x41d bytes    
PresentationCore.dll!System.Windows.Input.InputManager.RaiseProcessInputEventHandlers(System.Windows.Input.ProcessInputEventHandler postProcessInput, System.Windows.Input.ProcessInputEventArgs processInputEventArgs) + 0x9d bytes    
PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() + 0x23b bytes   
PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) + 0x45 bytes 
PresentationCore.dll!System.Windows.Input.TextCompositionManager.UnsafeStartComposition(System.Windows.Input.TextComposition composition) + 0x74 bytes  
PresentationCore.dll!System.Windows.Input.TextCompositionManager.PostProcessInput(object sender, System.Windows.Input.ProcessInputEventArgs e) + 0x6ca bytes    
PresentationCore.dll!System.Windows.Input.InputManager.RaiseProcessInputEventHandlers(System.Windows.Input.ProcessInputEventHandler postProcessInput, System.Windows.Input.ProcessInputEventArgs processInputEventArgs) + 0x9d bytes    
PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() + 0x23b bytes   
PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) + 0x45 bytes 
PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport) + 0x62 bytes  
PresentationCore.dll!System.Windows.Interop.HwndKeyboardInputProvider.ProcessTextInputAction(System.IntPtr hwnd, MS.Internal.Interop.WindowMessage msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x189 bytes 
PresentationCore.dll!System.Windows.Interop.HwndSource.OnPreprocessMessage(object param) + 0x2c6 bytes  
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x53 bytes 
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) + 0x42 bytes    
WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) + 0xb4 bytes    
PresentationCore.dll!System.Windows.Interop.HwndSource.OnPreprocessMessageThunk(ref System.Windows.Interop.MSG msg, ref bool handled) + 0xc6 bytes  
PresentationCore.dll!System.Windows.Interop.HwndSource.WeakEventPreprocessMessage.OnPreprocessMessage(ref System.Windows.Interop.MSG msg, ref bool handled) + 0x35 bytes    
WindowsBase.dll!System.Windows.Interop.ComponentDispatcherThread.RaiseThreadMessage(ref System.Windows.Interop.MSG msg) + 0x3d bytes    
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0xaa bytes  
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes  
PresentationFramework.dll!System.Windows.Window.ShowHelper(object booleanBox) + 0x181 bytes 
PresentationFramework.dll!System.Windows.Window.Show() + 0x61 bytes 
PresentationFramework.dll!System.Windows.Window.ShowDialog() + 0x2d0 bytes  
JieMeiTaoInventoryManager.exe!JieMeiTaoInventoryManager.MainWindow.NewItemCommandBinding_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) Line 291 + 0xd bytes   C#
PresentationCore.dll!System.Windows.Input.CommandBinding.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) + 0x63 bytes 
PresentationCore.dll!System.Windows.Input.CommandManager.ExecuteCommandBinding(object sender, System.Windows.Input.ExecutedRoutedEventArgs e, System.Windows.Input.CommandBinding commandBinding) + 0x98 bytes  
PresentationCore.dll!System.Windows.Input.CommandManager.FindCommandBinding(System.Windows.Input.CommandBindingCollection commandBindings, object sender, System.Windows.RoutedEventArgs e, System.Windows.Input.ICommand command, bool execute) + 0x10a bytes  
PresentationCore.dll!System.Windows.Input.CommandManager.FindCommandBinding(object sender, System.Windows.RoutedEventArgs e, System.Windows.Input.ICommand command, bool execute) + 0x1a0 bytes 
PresentationCore.dll!System.Windows.Input.CommandManager.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) + 0x26 bytes 
PresentationCore.dll!System.Windows.UIElement.OnExecutedThunk(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) + 0x59 bytes   
PresentationCore.dll!System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(System.Delegate genericHandler, object target) + 0x3e bytes    
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) + 0x29 bytes  
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) + 0x3e bytes    
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) + 0xbe bytes   
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) + 0x79 bytes  
PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args) + 0x41 bytes   
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) + 0x2c bytes    
PresentationCore.dll!System.Windows.Input.RoutedCommand.ExecuteImpl(object parameter, System.Windows.IInputElement target, bool userInitiated) + 0x111 bytes    
PresentationCore.dll!System.Windows.Input.RoutedCommand.ExecuteCore(object parameter, System.Windows.IInputElement target, bool userInitiated) + 0x5b bytes 
PresentationCore.dll!System.Windows.Input.CommandManager.TranslateInput(System.Windows.IInputElement targetElement, System.Windows.Input.InputEventArgs inputEventArgs) + 0x3df bytes   
PresentationCore.dll!System.Windows.UIElement.OnKeyDownThunk(object sender, System.Windows.Input.KeyEventArgs e) + 0x67 bytes   
PresentationCore.dll!System.Windows.Input.KeyEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) + 0x34 bytes    
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) + 0x29 bytes  
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) + 0x3e bytes    
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) + 0xbe bytes   
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) + 0x79 bytes  
PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args) + 0x41 bytes   
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) + 0x2c bytes    
PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() + 0x1ff bytes   
PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) + 0x45 bytes 
PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport) + 0x62 bytes  
PresentationCore.dll!System.Windows.Interop.HwndKeyboardInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawKeyboardActions actions, int scanCode, bool isExtendedKey, bool isSystemKey, int virtualKey) + 0x101 bytes    
PresentationCore.dll!System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(ref System.Windows.Interop.MSG msg, ref bool handled) + 0xf4 bytes   
PresentationCore.dll!System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(ref System.Windows.Interop.MSG msg, System.Windows.Input.ModifierKeys modifiers) + 0x8f bytes   
PresentationCore.dll!System.Windows.Interop.HwndSource.OnPreprocessMessage(object param) + 0x106 bytes  
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x53 bytes 
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) + 0x42 bytes    
WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) + 0xb4 bytes    
PresentationCore.dll!System.Windows.Interop.HwndSource.OnPreprocessMessageThunk(ref System.Windows.Interop.MSG msg, ref bool handled) + 0xc6 bytes  
PresentationCore.dll!System.Windows.Interop.HwndSource.WeakEventPreprocessMessage.OnPreprocessMessage(ref System.Windows.Interop.MSG msg, ref bool handled) + 0x35 bytes    
WindowsBase.dll!System.Windows.Interop.ComponentDispatcherThread.RaiseThreadMessage(ref System.Windows.Interop.MSG msg) + 0x3d bytes    
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0xaa bytes  
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes  
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x5b bytes  
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x74 bytes 
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x2b bytes 
PresentationFramework.dll!System.Windows.Application.Run() + 0x1b bytes 
JieMeiTaoInventoryManager.exe!JieMeiTaoInventoryManager.App.Main() + 0x5e bytes C#
[Native to Managed Transition]  
[Managed to Native Transition]  
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x6d bytes    
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2a bytes  
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x63 bytes   
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0xb0 bytes    
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x2c bytes    
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes   
[Native to Managed Transition]  

更新: プログラムが Validate メソッドにヒットするたびに、次の行が繰り返し呼び出されることに気付きました。

    PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.SetValue(object item, object value) + 0x171 bytes 
PresentationFramework.dll!MS.Internal.Data.ClrBindingWorker.UpdateValue(object value) + 0xa3 bytes  
PresentationFramework.dll!System.Windows.Data.BindingExpression.UpdateSource(object value) + 0x99 bytes 
PresentationFramework.dll!System.Windows.Data.BindingExpressionBase.UpdateValue() + 0x66 bytes  
PresentationFramework.dll!System.Windows.Data.BindingExpression.Update(bool synchronous) + 0x4f bytes   
PresentationFramework.dll!System.Windows.Data.BindingExpressionBase.Dirty() + 0x30 bytes    
PresentationFramework.dll!System.Windows.Data.BindingExpression.SetValue(System.Windows.DependencyObject d, System.Windows.DependencyProperty dp, object value) + 0x27 bytes    
WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal) + 0x3c7 bytes  

更新 2 私の Validate メソッドが新しい ValidationResult(false,xxx) を返す場合、無限ループは発生しません。ValidationResult(false,xxx) がどこかでループを停止するイベントをトリガーするかどうか疑問に思っていますか?

4

1 に答える 1