Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange WPF error

Tags:

c#

.net

wpf

xaml

blend

I have some code that works intermittently and I can't understand why (worked perfectly until today morning when windows automatically installed some updates, but none related to .NET 4 - version used in my project).

My password box ...

<PasswordBox x:Name="TboxPassword" Grid.Row="1" Grid.Column="0" 
                controls:TextboxHelper.Watermark="Password ..."
                controls:TextboxHelper.ClearTextButton="True"
                Margin="10, 10, 0, 0">
    <i:Interaction.Behaviors>
        <misc:PasswordBoxBehavior Password="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"/>
    </i:Interaction.Behaviors>
</PasswordBox>

My behavior:

public class PasswordBoxBehavior : Behavior<PasswordBox>
{
    #region Fields

    private readonly object _tryToExecuteActionSyncObject = new object();
    private bool _isUpdating;

    #endregion

    #region Properties

    public string Password
    {
        get { return (string)GetValue(PasswordProperty); }
        set { SetValue(PasswordProperty, value); }
    }

    public static readonly DependencyProperty PasswordProperty =
        DependencyProperty.Register("Password", typeof(string), typeof(PasswordBoxBehavior),
        new PropertyMetadata(string.Empty, OnPasswordPropertyChanged));

    #endregion

    #region Methods

    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.PasswordChanged += OnAssociatedObjectPasswordChanged;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        AssociatedObject.PasswordChanged -= OnAssociatedObjectPasswordChanged;
    }

    private void OnAssociatedObjectPasswordChanged(object sender, RoutedEventArgs e)
    {
        TryToExecuteAction(() => Password = AssociatedObject == null
            ? string.Empty
            : AssociatedObject.Password);
    }

    private static void OnPasswordPropertyChanged
        (DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        PasswordBoxBehavior passwordBoxBehavior;
        if (sender == null
            || (passwordBoxBehavior = sender as PasswordBoxBehavior) == null
            || passwordBoxBehavior.AssociatedObject == null)
        {
            return;
        }

        passwordBoxBehavior.TryToExecuteAction
            (() => passwordBoxBehavior.AssociatedObject.Password =
                    (e.NewValue == null
                        ? string.Empty
                        : (string) e.NewValue));
    }

    private void TryToExecuteAction(Action actionToExecute)
    {
        bool continueExecution;
        lock (_tryToExecuteActionSyncObject)
        {
            continueExecution = _isUpdating == false;
            _isUpdating = true;
        }

        if (continueExecution == false)
        {
            return;
        }

        try
        {
            if (actionToExecute != null)
            {
                actionToExecute();
            }
        }
        finally
        {
            lock (_tryToExecuteActionSyncObject)
            {
                _isUpdating = false;
            }
        }
    }

    #endregion
}

I get 0 (zero) compilation errors. When running the application, 90% of the time I'm getting a runtime exception stating that:

{"Cannot add instance of type 'PasswordBoxBehavior' to a collection of type 'BehaviorCollection'. Only items of type 'T' are allowed."}

Debugger stops at the tag Interaction.Behaviors

Please keep in mind that I never received this error until today. Now I receive it even after I revert everything I done today.

Please advise .. :D

PS: I just commented out all the code from inside the behavior. Also removed the Password binding. Still doesn't work :(

PPS: If I close Visual Studio (2012), delete my bin folder, open VS, open project, rebuild all, the application WORKS until the first change to the code.

like image 569
smiron Avatar asked Sep 30 '22 05:09

smiron


2 Answers

I know this question is very old. But I will post the answer in case someone face it again.

I just came across the same issue and I found a solution, I noticed that you are using behaviors in your code. Just make sure that your are referencing the right version of Blend SDK Windows.Interactivity

In my case the problem was that I installed the NugetPackage for Blend SDK for WPF 4.5 only on the main WPF project, and I forgot to install it on the other WPF projects in the solution that uses behaviors.

I solved the problem by installing the same NugetPackage on the project containing the code causing the problem.

Hope this helps you!

like image 96
Mohammed A. Fadil Avatar answered Oct 08 '22 06:10

Mohammed A. Fadil


Blend SDK Windows.Interactivity has been abandoned, and the file System.Windows.Interactivity.dll has been removed from GAC. Use Microsoft.Xaml.Behaviors.Wpf instead, you can install it from Nuget.org.

If you switch the "interactive library" from Blend SDK Windows.Interactivity(System.Windows.Interactivity) to Microsoft.Xaml.Behaviors.Wpf(Microsoft.Xaml.Behaviors) You can:

  1. Remove System.Windows.Interactivity reference from project.
  2. Close/Unload this solution/project, and open the solution/project directory.
  3. Delete belows folders :.vs, bin, obj.
  4. Reopen/Reload the solution/project.
  5. Replace all namespace of System.Windows.Interactivity to Microsoft.Xaml.Behaviors
  6. Build the solution/project.

Then it will be fine.

like image 36
Mr. Squirrel.Downy Avatar answered Oct 08 '22 08:10

Mr. Squirrel.Downy