2

UPDATED (See below)

WPF starts ignoring property change notifications after a minute of intensive work. Here is a demo to reproduce (also on GitHub). View model is:

[Aggregatable]
[NotifyPropertyChanged]
[ContentProperty("Tests")]
public class Model
{
    [Child] public AdvisableCollection<Test> Tests { get; } = new AdvisableCollection<Test>();
    [Child] public Test Test { get; set; }
}

Where:

[Aggregatable]
[NotifyPropertyChanged]
public class Test
{
    public string Name { get; set; }
    [Parent] public Model Model { get; private set; }
}

XAML:

<Window x:Class="Demo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Demo"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:Model>
            <local:Test Name="a"/>
            <local:Test Name="b"/>
            <local:Test Name="c"/>
            <local:Test Name="d"/>
        </local:Model>
    </Window.DataContext>
    <TextBox DockPanel.Dock="Top" Text="{Binding Test.Name, Mode=OneWay}"/>
</Window>

And the code behind:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Timer = new DispatcherTimer();
        Timer.Interval = TimeSpan.FromMilliseconds(250);
        Timer.Tick += Timer_Tick;
        Timer.Start();
    }

    DispatcherTimer Timer { get; }
    Random Random = new Random();
    Model Model => DataContext as Model;

    private void Timer_Tick(object sender, EventArgs e)
    {
        var i = Random.Next(Model.Tests.Count);
        Model.Test = Model.Tests[i];
    }
}

Run it and wait a minute – window will get frozen. Any ideas how to fix it?

UPDATE

I simplified the model - this one is still gets frozen in a minute:

[NotifyPropertyChanged]
[ContentProperty("Tests")]
public class Model
{
    public List<Test> Tests { get; } = new List<Test>();
    public Test Test { get; set; }
}

[NotifyPropertyChanged]
public class Test
{
    public string Name { get; set; }
}

But the following version of Test class solves the problem:

public class Test : INotifyPropertyChanged
{
    public string Name { get; set; }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
Dmitry Nogin
  • 3,670
  • 1
  • 19
  • 35
  • The issue was fixed in PostSharp 6.0.28. – Daniel Balas Oct 08 '18 at 16:33
  • When I see a question about PostSharp's [NotifyPropertyChanged] my responsibility is to mention a superior alternative: Stepen Cleary's Calculated Properties. https://github.com/StephenCleary/CalculatedProperties/blob/master/README.md I used both and IMO there's zero reasons to use Postsharp INPC for MVVM. Calculated Properties can do everything that PostSharp does plus loops methods LINQ basically any crazy dependencies that you can imagine doesn't matter how indirect, dependency graph rewires at runtime and just works. They are faster and also free. – KolA Apr 03 '19 at 07:16

1 Answers1

3

It looks like this issue is caused by incompatibility between the weak event manager of the NotifyPropertyChanged aspect and the weak event manager in the WPF. As a workaround, you can disable the aspect's weak events implementation when applying the aspect to the target element:

[NotifyPropertyChanged( WeakEventStrategy = WeakEventStrategy.AlwaysStrong )]
[ContentProperty("Tests")]
public class Model
{
    // ...
}

[NotifyPropertyChanged( WeakEventStrategy = WeakEventStrategy.AlwaysStrong )]
public class Test
{
    // ...
}

We will continue to investigate the issue and we'll update the answer once the fix is released.

EDIT: This issue was fixed in PostSharp 6.0.28.

Daniel Balas
  • 1,805
  • 1
  • 15
  • 20
AlexD
  • 5,011
  • 2
  • 23
  • 34