使用PostSharp跟踪属性更改

时间:2018-09-17 02:10:14

标签: c# wpf xaml postsharp .net-4.7.2

我想在前面的所有页面均有效时启用给定的向导页面。这是我的视图模型:

[Aggregatable]
[NotifyPropertyChanged]
[ContentProperty("Pages")]
public class Wizard
{
    [Child, AggregateAllChanges] 
    public AdvisableCollection<Page> Pages { get; } = new AdvisableCollection<Page>();
}

这里是Page本身:

[Aggregatable]
[NotifyPropertyChanged]
public class Page : INotifyPropertyChanged
{
    [Parent] Wizard Wizard { get; set; }
    public string Name { get; set; }
    public bool Valid { get; set; }

    [SafeForDependencyAnalysis]
    public bool Enabled
    {
        get
        {
            if(Depends.Guard)
                Depends.On(Wizard.Pages);

            return Wizard.Pages
                .TakeWhile(p => p != this)
                .All(p => p.Valid);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    void OnPropertyChanged(string propertyName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        if (Wizard != null)
            NotifyPropertyChangedServices.SignalPropertyChanged(Wizard, nameof(Wizard.Pages));
    }
}

我期望Enabled更改时,PostSharp会通知Wizard.Pages属性更改。不幸的是,它无法正常工作-Enabled属性没有更新。此代码有什么问题?

要测试的XAML:

<Window.DataContext>
    <local:Wizard>
        <local:Page Name="First"/>
        <local:Page Name="Second"/>
        <local:Page Name="Third"/>
        <local:Page Name="Forth"/>
    </local:Wizard>
</Window.DataContext>
<ListBox ItemsSource="{Binding Pages}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type local:Page}">
            <CheckBox Content="{Binding Name}" IsChecked="{Binding Valid}" IsEnabled="{Binding Enabled}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox> 

1 个答案:

答案 0 :(得分:0)

我们已经对提供的示例进行了调查,原因似乎是NotifyPropertyChangedAggregatable两个方面之间的兼容性问题。

如果您删除或注释掉[Aggregatable]属性,则会为Enabled属性引发事件,如预期的那样。实际上,将Wizard属性标记为引用而不是将其标记为父项足以解决NPC行为。一旦Wizard属性未标记为父级,您将需要通过手动设置该属性来确保值正确。

请注意,还需要在OnPropertyChanged方法中添加属性名称检查,以避免无限循环“ Wizard.Pages更改”->“ Enabled更改”->“ Wizard.Pages更改”。 ..

[Aggregatable]
[NotifyPropertyChanged]
public class Page : INotifyPropertyChanged
{
    //[Parent]
    [Reference]
    public Wizard Wizard { get; set; }
    public string Name { get; set; }
    public bool Valid { get; set; }

    [SafeForDependencyAnalysis]
    public bool Enabled
    {
        get
        {
            if ( Depends.Guard )
                Depends.On( Wizard.Pages );

            return Wizard.Pages
                .TakeWhile( p => p != this )
                .All( p => p.Valid );
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    void OnPropertyChanged( string propertyName )
    {
        PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
        if ( Wizard != null && propertyName != nameof( Enabled ) )
            NotifyPropertyChangedServices.SignalPropertyChanged( Wizard, nameof( Wizard.Pages ) );
    }
}

我们将继续调查该问题,并在修复程序发布后更新答案。

更新。 PostSharp版本6.0.29已修复NotifyPropertyChangedAggregatable之间的兼容性错误。请更新您的NuGet软件包到最新版本。