Отслеживание изменений свойств с помощью PostSharp - PullRequest
0 голосов
/ 17 сентября 2018

Я хотел бы включить данную страницу мастера, когда все предыдущие страницы действительны.Вот моя модель представления:

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

Я ожидал, что PostSharp уведомит об изменении свойства Enabled при изменении 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 голосов
/ 19 сентября 2018

Мы исследовали предоставленный образец, и похоже, что причиной является проблема совместимости между NotifyPropertyChanged и Aggregatable аспектами.

Если вы удалите или закомментируете атрибуты [Aggregatable], событие генерируется для свойства Enabled, как и ожидалось. На самом деле, даже достаточно пометить свойство Wizard как ссылку вместо родителя, чтобы исправить поведение NPC. Если свойство Wizard не помечено как родительское, вам нужно будет указать правильное значение, установив свойство вручную.

Обратите внимание, что вам также необходимо добавить проверку имени свойства в методе OnPropertyChanged, чтобы избежать бесконечного цикла «Wizard.Pages change» -> «Enabled updated» -> «Wizard.Pages changes» ...

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

Мы продолжим изучение проблемы и обновим ответ, как только будет выпущено исправление.

ОБНОВЛЕНИЕ. Ошибка совместимости между аспектами NotifyPropertyChanged и Aggregatable была исправлена ​​в PostSharp версии 6.0.29. Пожалуйста, обновите ваши пакеты NuGet до последней версии.

...