OnPropertyChanged не распознается Binding - PullRequest
0 голосов
/ 23 января 2020

У меня есть несколько фигур, где я хочу изменить непрозрачность, когда я нажимаю на нее, кроме того, мне нужно знать в коде, какие фигуры были выбраны, и мне нужно установить непрозрачность из кода позади.

Моя идея это использовать Dictionary<int, bool> с индексом и если выбрано или нет. Я знаю, что Dictionary не реализует INotifyCollectionChanged или INotifyPropertyChanged, но я нашел пример наблюдаемого словаря, который очень хорошо запускает оба события.

Для каждой фигуры (прямоугольника) я устанавливаю следующую привязку :

<Rectangle Height="25" Stroke="Black" Margin="10" Fill="AliceBlue" StrokeThickness="3">
    <Rectangle.Style>
        <Style TargetType="Rectangle">
            <EventSetter Event="PreviewMouseDown" Handler="Rectangle_PreviewMouseDown"></EventSetter>
            <Setter Property="local:IndexProperty.SectorIndex" Value="1"></Setter>
            <Setter Property="local:SelectSectorProperty.SelectedSector" Value="{Binding SelectedRect, Mode=OneWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"></Setter>
        </Style>
    </Rectangle.Style>
</Rectangle>

В пределах Rectangle_PreviewMouseDown Я переключаю значение bool ObservableDictionary<int, bool> с помощью SectorIndex.

Присоединенное свойство выглядит следующим образом:

public class SelectSectorProperty : DependencyObject
{
    public static ObservableDictionary<int, bool> GetSelectedSector(DependencyObject obj)
    {
        return (ObservableDictionary<int, bool>)obj.GetValue(SelectedSectorProperty);
    }

    public static void SetSelectedSector(DependencyObject obj, ObservableDictionary<int, bool> value)
    {
        obj.SetValue(SelectedSectorProperty, value);
    }

    // Using a DependencyProperty as the backing store for SectorList.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SelectedSectorProperty =
        DependencyProperty.RegisterAttached("SelectedSector", typeof(ObservableDictionary<int, bool>),
            typeof(SelectSectorProperty), new PropertyMetadata(OnStatusChanged));

    private static void OnStatusChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        Debug.WriteLine("OnStatusChanged");
        if (obj is Rectangle element)
        {
            if (e.NewValue?.GetType() == typeof(ObservableDictionary<int, bool>))
            {
                var index = (int)obj.GetValue(IndexProperty.SectorIndexProperty);
                GetSelectedSector(obj).TryGetValue(index, out bool selected);
                if (selected)
                {
                    element.Opacity = 0.8;
                }
                else
                {
                    element.Opacity = 0.1;
                }
            }
        }
    }
}

Моя ViewModel is this:

public class ViewModel : ViewModelBase
{
    public ViewModel()
    {
        SelectedRect.PropertyChanged += SelectedSectors_PropertyChanged;
    }

    private void SelectedSectors_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        OnPropertyChanged(nameof(SelectedRect));
    }

    private ObservableDictionary<int, bool> _SelectedRect = new ObservableDictionary<int, bool>() {
        { 1, false},
        { 2, false},
        { 3, false},
    };
    public ObservableDictionary<int, bool> SelectedRect
    {
        get { return _SelectedRect; }
        set
        {
            _SelectedRect = value;
            OnPropertyChanged(nameof(SelectedRect));
        }
    }
}

После обновления моего ObservableDictionary запускается событие SelectedRect.PropertyChanged, а также вызывается событие OnPropertyChanged, реализованное в классе ViewModelBase, с точно таким же параметры, которые будут вызываться из самого свойства SelectedRect. Но OnStatusChanged моего присоединенного свойства не сработает, только если я изменю ссылку на мое свойство SelectedRect (например, установив значение null и вернусь к нему).

Это отличается от моих ожиданий, я бы действительно хотелось бы знать почему, достаточно вызвать OnPropertyChanged с правильными параметрами, но кажется, что за кулисами происходит больше проверки.

Я думаю, что явное обновление Binding - это путь к go?

...