question

StoutGamer avatar image
0 Votes"
StoutGamer asked StoutGamer commented

WPF Behaviors no longer working with newest NuGets.

Hi. The app used to work fine, but a few weeks ago we updated hundreds of NuGet packages. We recently discovered that any reference to a WPF Behavior gives the following error:

System.Windows.Markup.XamlParseException: ''Add value to collection of
type 'Microsoft.Xaml.Behaviors.BehaviorCollection' threw an
exception.' Line number '78' and line position '86'.'

Inner Exception ArgumentException: Cannot add instance of type
'TextBoxInputBehavior' to a collection of type 'BehaviorCollection'.
Only items of type 'T' are allowed.

I suspect this is because of a NuGet update, but I don't know which one had caused the error, or which need to be changed. I'm using the latest version for Microsoft.Xaml.Behaviors.Wpf (1.1.31).

I would appreciate advice. Thanks.

Code:

          xmlns:Behaviors="clr-namespace:MyCompany.MyProject"
          xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

             <TextBox Text="...">
                 <i:Interaction.Behaviors>
                     <Behaviors:TextBoxInputBehavior InputMode="DecimalInput" JustPositiveDecimalInput="False" RangeMin="-1000000.000" RangeMax="1000000.000" />
                 </i:Interaction.Behaviors>
             </TextBox>


Edit: TextBoxInputBehavior below. Looks like it's been copied as-is from here.


 using Microsoft.Xaml.Behaviors;
    
 public class TextBoxInputBehavior : Behavior<TextBox>
 {
     const NumberStyles validNumberStyles = NumberStyles.AllowDecimalPoint |
                                                NumberStyles.AllowThousands |
                                                NumberStyles.AllowLeadingSign;
     public TextBoxInputBehavior()
     {
         this.InputMode = TextBoxInputMode.None;
         this.JustPositivDecimalInput = false;
     }
    
     public TextBoxInputMode InputMode { get; set; }
    
    
     public static readonly DependencyProperty JustPositivDecimalInputProperty =
      DependencyProperty.Register("JustPositivDecimalInput", typeof(bool),
      typeof(TextBoxInputBehavior), new FrameworkPropertyMetadata(false));
    
     public bool JustPositivDecimalInput
     {
         get { return (bool)GetValue(JustPositivDecimalInputProperty); }
         set { SetValue(JustPositivDecimalInputProperty, value); }
     }
    
     protected override void OnAttached()
     {
         base.OnAttached();
         AssociatedObject.PreviewTextInput += AssociatedObjectPreviewTextInput;
         AssociatedObject.PreviewKeyDown += AssociatedObjectPreviewKeyDown;
    
         DataObject.AddPastingHandler(AssociatedObject, Pasting);
    
     }
    
     protected override void OnDetaching()
     {
         base.OnDetaching();
         AssociatedObject.PreviewTextInput -= AssociatedObjectPreviewTextInput;
         AssociatedObject.PreviewKeyDown -= AssociatedObjectPreviewKeyDown;
    
         DataObject.RemovePastingHandler(AssociatedObject, Pasting);
     }
    
     private void Pasting(object sender, DataObjectPastingEventArgs e)
     {
         if (e.DataObject.GetDataPresent(typeof(string)))
         {
             var pastedText = (string)e.DataObject.GetData(typeof(string));
    
             if (!this.IsValidInput(this.GetText(pastedText)))
             {
                 System.Media.SystemSounds.Beep.Play();
                 e.CancelCommand();
             }
         }
         else
         {
             System.Media.SystemSounds.Beep.Play();
             e.CancelCommand();
         }
     }
    
     private void AssociatedObjectPreviewKeyDown(object sender, KeyEventArgs e)
     {
         if (e.Key == Key.Space)
         {
             if (!this.IsValidInput(this.GetText(" ")))
             {
                 System.Media.SystemSounds.Beep.Play();
                 e.Handled = true;
             }
         }
     }
    
     private void AssociatedObjectPreviewTextInput(object sender, TextCompositionEventArgs e)
     {
         if (!this.IsValidInput(this.GetText(e.Text)))
         {
             System.Media.SystemSounds.Beep.Play();
             e.Handled = true;
         }
     }
    
     private string GetText(string input)
     {
         var txt = this.AssociatedObject;
    
         int selectionStart = txt.SelectionStart;
         if (txt.Text.Length < selectionStart) 
             selectionStart = txt.Text.Length;
    
         int selectionLength = txt.SelectionLength;
         if (txt.Text.Length < selectionStart + selectionLength) 
             selectionLength = txt.Text.Length - selectionStart;
    
         var realtext = txt.Text.Remove(selectionStart, selectionLength);
    
         int caretIndex = txt.CaretIndex;
         if (realtext.Length < caretIndex) 
             caretIndex = realtext.Length;
    
         var newtext = realtext.Insert(caretIndex, input);
    
         return newtext;
     }
    
     private bool IsValidInput(string input)
     {
         switch (InputMode)
         {
             case TextBoxInputMode.None:
                 return true;
             case TextBoxInputMode.DigitInput:
                 return CheckIsDigit(input);
    
             case TextBoxInputMode.DecimalInput:
                 decimal d;
                 //wen mehr als ein Komma
                 if (input.ToCharArray().Where(x => x == ',').Count() > 1)
                     return false;
    
                 if (input.Contains("-"))
                 {
                     if (this.JustPositivDecimalInput) 
                         return false;
    
                     //minus einmal am anfang zulässig
                     if (input.IndexOf("-",StringComparison.Ordinal) == 0  && input.ToCharArray().Count(x=>x=='-') == 1)
                         return true;
                 }
    
                 var result = decimal.TryParse(input, validNumberStyles, CultureInfo.CurrentCulture, out d);
                 return result;
    
    
    
             default: throw new ArgumentException("Unknown TextBoxInputMode");
    
         }
         return true;
     }
    
     private bool CheckIsDigit(string wert)
     {
         return wert.ToCharArray().All(Char.IsDigit);
     }
 }
    
 public enum TextBoxInputMode
 {
     None,
     DecimalInput,
     DigitInput
 }


windows-wpf
· 6
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@StoutGamer
I use your code in my WPF .netcore 5 app and it runs without error . Did your project meet the Dependencies as below shown of the NuGet package?
110420-capture.png


1 Vote 1 ·
capture.png (3.9 KiB)

Hi @DaisyTian-MSFT . Thank you so much for the advice. This is a .NET Framework 4.7.2, not .netcore. Could that be the problem?

Thank you.


111066-dotnetframework472.png


0 Votes 0 ·

@StoutGamer
I can't reproduce your error with the above the code. Could you show the code of TextBoxInputBehavior for me to make a sample in Framework4.7.2 to reproduce your error?

1 Vote 1 ·
Show more comments

0 Answers