uwp: программная проблема с привязкой данных

#xaml #data-binding #uwp #binding #programmatically

#xaml #привязка данных #uwp #привязка #программно

Вопрос:

я разрабатываю с помощью uwp, и у меня проблема с привязкой данных. У меня есть ListView, который я заполняю пользовательскими элементами панели, называемыми классом PlaylistLeftOption. Этот класс наследует атрибуты класса Panel, которые наследуют атрибут класса FrameworkElement и его методы, поэтому у меня есть доступный метод привязки. Теперь я пытаюсь привязать значение высоты (оно равно другим элементам), поэтому я создал статический атрибут, называемый PerformanceItemHeight, в другом внешнем одноэлементном классе. поскольку мне нужно динамически заполнять listview, я пытаюсь привязать значение внутри конструктора, но это не работает. Это код внутри конструктора:

     public PlaylistLeftOption()
    {
        mainGrid.Background = new SolidColorBrush(Colors.Red);
        mainGrid.BorderBrush = new SolidColorBrush(Colors.Black);
        mainGrid.BorderThickness = new Thickness(0.5,0.25,0.5,0.25);

        WidthVal = 200;
        HeightVal = 50;

        var myBinding = new Binding();
        myBinding.Source = PerformanceLayout.Instance.PerformanceItemHeight;
        myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        myBinding.Mode = BindingMode.TwoWay;
        SetBinding(HeightValProperty, myBinding);

        Children.Add(mainGrid);
    }
 

И это свойство:

      public static readonly DependencyProperty HeightValProperty = DependencyProperty.Register(
      "HeightVal",
      typeof(double),
      typeof(PlaylistLeftOption),
      new PropertyMetadata(50)
    );

    public double HeightVal
    {
        get => (double)GetValue(HeightValProperty);
        set
        {
            SetValue(HeightValProperty, value);
            Height = HeightVal;
            mainGrid.Height = HeightVal;
            globalSize.Height = HeightVal;
        }
    }
 

Это код для PerformanceItemHeight:

     public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private double _performanceItemHeight = 50;
    public double PerformanceItemHeight {
        get => _performanceItemHeight;
        set {
            _performanceItemHeight = value;
            this.OnPropertyChanged();
        }
    }
 

Почему это работает через xaml?
я попытался добавить элемент PlaylistLeftOption внутри listview через xaml, и все в порядке!
Спасибо

Ответ №1:

При тестировании привязка HeightVal работает в XAML, а привязка HeightVal не работает в коде. Вы можете увидеть причину в разделе Реализация оболочки свойств пользовательских зависимостей документа, в котором говорится, что ваши реализации оболочки должны выполнять только операции GetValue и setValue . В противном случае вы получите другое поведение, когда ваше свойство задается с помощью XAML, по сравнению с тем, когда оно задается с помощью кода.

Вы могли бы добавить метод обратного вызова с измененным свойством, чтобы активно уведомлять об изменениях HeightVal .

Например:

 public static readonly DependencyProperty HeightValProperty = DependencyProperty.Register(
  "HeightVal",
  typeof(double),
  typeof(PlaylistLeftOption),
  new PropertyMetadata(100, new PropertyChangedCallback(OnHeightValChanged))
);
private static void OnHeightValChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    PlaylistLeftOption playlistLeftOption = d as PlaylistLeftOption;
    if(playlistLeftOption != null)
    {
        var height = (Double)e.NewValue;
        playlistLeftOption.HeightVal = height;
    }
}
 

И измените код привязки следующим образом:

 var myBinding = new Binding();
myBinding.Source = PerformanceLayout.Instance;
myBinding.Path = new PropertyPath("PerformanceItemHeight");
myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
myBinding.Mode = BindingMode.TwoWay;
SetBinding(HeightValProperty, myBinding);
 

Комментарии:

1. Янгу большое вам спасибо! Он работает правильно!

2. Если ответ решил вашу проблему, пожалуйста, отметьте его как принятый