使用 PostSharp 跟踪属性更改 [英] Tracking property changes with PostSharp

查看:17
本文介绍了使用 PostSharp 跟踪属性更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to enable a given wizard page when all preceding pages are valid. Here is my view model:

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

我希望 PostSharp 在 Wizard.Pages 更改时通知 Enabled 属性更改.不幸的是它不起作用 - Enabled 属性没有更新.这段代码有什么问题?

I was expecting PostSharp to notify about Enabled property change when Wizard.Pages changes. It does not work unfortunately – there is no updates to Enabled properties. What is wrong about this code?

要测试的 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> 

推荐答案

我们已经调查了提供的样本,看起来原因是 NotifyPropertyChangedAggregatable 之间的兼容性问题代码>方面.

We have investigated the provided sample and it looks like the cause is a compatibility issue between the NotifyPropertyChanged and Aggregatable aspects.

如果您删除或注释掉 [Aggregatable] 属性,则会按预期为 Enabled 属性引发事件.实际上,甚至将 Wizard 属性标记为引用而不是父属性来修复 NPC 行为就足够了.一旦 Wizard 属性没有被标记为父属性,您需要通过手动设置属性来确保正确的值.

If you remove or comment out the [Aggregatable] attributes, then the event is raised for the Enabled property as expected. Actually, it's even enough to mark the Wizard property as a reference instead of parent to fix the NPC behavior. Once the Wizard property is not marked as a parent, you'll need to ensure the correct value by setting the property manually.

请注意,您还需要在OnPropertyChanged方法中添加属性名称检查,以避免无限循环Wizard.Pages changed"->Enabled changed"->Wizard.Pages改变了"...

Please note, that you also need to add a property name check in the OnPropertyChanged method to avoid the infinite loop "Wizard.Pages changed" -> "Enabled changed" -> "Wizard.Pages changed"...

[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 ) );
    }
}

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

We'll continue investigating the issue and we'll update the answer once the fix is released.

更新. NotifyPropertyChangedAggregatable 方面之间的兼容性错误已在 PostSharp 6.0.29 版中修复.请将您的 NuGet 包更新到最新版本.

UPDATE. The compatibility bug between the NotifyPropertyChanged and Aggregatable aspects has been fixed in PostSharp version 6.0.29. Please update your NuGet packages to the latest version.

这篇关于使用 PostSharp 跟踪属性更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆