WPF IsEnabled Привязка к свойству в коллекции, которая зависит от другого свойства в другой коллекции - PullRequest
0 голосов
/ 20 февраля 2020

Ссылка на решение: https://github.com/fallingsappy/portfolio/tree/master/DDrop

Привет всем! У меня проблема с привязкой IsEnabled для TabItem. Это сложно объяснить, но я стараюсь. У меня есть коллекция под названием Пользователь. Пользователь содержит коллекцию UserSeries класса Series. У UserSeries есть еще одна коллекция под названием DropPhotosSeries. Также UserSeries имеет свойство с именем:

private bool _canDrawPlot;
public bool CanDrawPlot
{
    get
    {
        return _dropPhotosSeries?.Where(x => x.Drop.RadiusInMeters != null).ToList().Count > 1 && _dropPhotosSeries?.Where(x => x.Drop.RadiusInMeters == null).ToList().Count == 0;
    }
    set
    {
        _canDrawPlot = value;
        OnPropertyChanged(new PropertyChangedEventArgs("CanDrawPlot"));
    }
}

На основе этого свойства. TabItem должен быть включен или отключен. Но этот TabItem не замечает изменений свойства. Я перепробовал много подходов, но все равно ничего. Вот немного XAML:

    <TabItem IsEnabled="{Binding ElementName=AppMainWindow, Path=User.IsAnySelectedSeriesCantDrawPlot}" Name="CombinedSeriesPlot" Header="Общий график серий">
        <uc:ScatterPlot User="{Binding User, ElementName=AppMainWindow, UpdateSourceTrigger=PropertyChanged}"/>
    </TabItem>

Часть кода:

public class User : INotifyPropertyChanged
{
    private ObservableCollection<Series> _userSeries;
    public ObservableCollection<Series> UserSeries
    {
        get
        {
            return _userSeries;
        }
        set
        {
            _userSeries = value;
            OnPropertyChanged(new PropertyChangedEventArgs("UserSeries"));
        }
    }

    private bool _isAnySelectedSeriesCantDrawPlot;
    [NotMapped]
    public bool IsAnySelectedSeriesCantDrawPlot
    {
        get
        {
            return _userSeries?.Where(x => x?.CanDrawPlot == false).ToList().Count > 0;
        }
        set
        {
            _isAnySelectedSeriesCantDrawPlot = value;
            OnPropertyChanged(new PropertyChangedEventArgs("IsAnySelectedSeriesCantDrawPlot"));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, e);
    }
}

Я пытался создать зависимое свойство в UserClass, но я думаю, что свойства в UserSeries должно быть достаточно:

public class Series : INotifyPropertyChanged
{
    private ObservableCollection<DropPhoto> _dropPhotosSeries;
    public ObservableCollection<DropPhoto> DropPhotosSeries
    {
        get
        {
            return _dropPhotosSeries;
        }
        set
        {
            _dropPhotosSeries = value;
            OnPropertyChanged(new PropertyChangedEventArgs("DropPhotosSeries"));
        }
    }

    private bool _canDrawPlot;
    public bool CanDrawPlot
    {
        get
        {
            return _dropPhotosSeries?.Where(x => x.Drop.RadiusInMeters != null).ToList().Count > 1 && _dropPhotosSeries?.Where(x => x.Drop.RadiusInMeters == null).ToList().Count == 0;
        }
        set
        {
            _canDrawPlot = value;
            OnPropertyChanged(new PropertyChangedEventArgs("CanDrawPlot"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, e);
    }
}

Может быть, DropPhoto должен выдать какое-то событие, которое CanDrowProperty нужно обновить сам и обновить TabItem? Я действительно не знаю. Но вот класс DropPhoto:

public class DropPhoto : INotifyPropertyChanged
{
    private Drop _drop;
    public Drop Drop
    {
        get
        {
            return _drop;
        }
        set
        {
            _drop = value;
            OnPropertyChanged(new PropertyChangedEventArgs("Drop"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, e);
    }
}

Он содержит класс Drop, который имеет свойство RadiusInMeters:

public class Drop : INotifyPropertyChanged
{
    private double? _radiusInMeters;
    public double? RadiusInMeters
    {
        get
        {
            return _radiusInMeters;
        }
        set
        {
            _radiusInMeters = value;
            OnPropertyChanged(new PropertyChangedEventArgs("RadiusInMeters"));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, e);
    }
}

Для полного решения. Пожалуйста, проверьте github ссылку.

1 Ответ

0 голосов
/ 22 февраля 2020

Трудно выяснить, что именно не так в вашем коде, но я постараюсь ответить прямо на вопрос простым примером кода

public class FirstClass : INotifyPropertyChanged
{
    SecondClass secondClass = new SecondClass();

    private bool _firstProperty;
    public bool FirstProperty
    {
        get => _firstProperty;
        set
        {
            _firstProperty = value;
            OnPropertyChanged(nameof(FirstProperty));
        }
    }

    private void SecondClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(secondClass.SecondProperty)) FirstProperty = secondClass.SecondProperty;
    }

    public FirstClass()
    {
        secondClass.PropertyChanged += SecondClass_PropertyChanged;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class SecondClass : INotifyPropertyChanged
{
    private bool _secondProperty;
    public bool SecondProperty
    {
        get => _secondProperty;
        set
        {
            _secondProperty = value;
            OnPropertyChanged(nameof(SecondProperty));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

В этом примере любое изменение SecondProperty приведет к изменению FirstProperty.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...