Заставить свойство зависимости всегда вызывать PropretyChangedCallback - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть CustomControl с DependencyProperty SetState.Это связано с MultiBinding (в одну сторону) с конвертером.Это все работает.

Таким образом, все правильно обновлено, событие PropertyChanged запускается, преобразователь получает значения, генерирует выходное значение, но свойство SetState не обновляется, если оно, например, имеет значение true, а преобразователь возвращает значение true какЧто ж.Поскольку я хочу, чтобы выполнялась логика сброса (см. Код ниже), я хочу, чтобы SetState всегда обновлялся, даже если значение, которое он будет установлен, совпадает с текущим значением.(если преобразователь выдает false и SetState имеет значение true, SetState будет должным образом обновлен до значения false, как и ожидалось)


MWE (напечатано на лету, извините за ошибки)

Просмотр

    <local:CustomControl>
        <local:CustomControl.SetState>
            <MultiBinding Converter="{local:MyConverter}">
                <Binding Path="MyProp1" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"/>
                <Binding Path="MyProp2" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"/>
            </MultiBinding>
        </local:CustomControl.SetState>
    </local:CustomControl>

Пользовательский элемент управления

   public class CustomControl : FrameworkElement
   {
      public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register(
              nameof(SetState),
              typeof(bool),
              typeof(CustomControl),
              new FrameworkPropertyMetadata(false, (s, e) =>
              {
                 ((CustomControl)s).SetState = (bool)e.NewValue;
              }));

      private bool _state;

      // For brevity i have used a boolean in the MWE
      public bool SetState
      {
         get { return _state; }
         set
         {
            // This is not called when the binding produces the same value as this property already has
            // but i want this to be set anyway to trigger the reset logic even though SetState property already equal the value being set.

            // Custom reset logic here

            _state = value;
         }
      }
   }

Преобразователь

  internal class MyConverter : MarkupExtension, IMultiValueConverter
   {
      private static MyConverter _instance;

      public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
      {
         // Imagine some complex logic here
         return ((bool)value[0] || (bool)value[1]);
      }

      public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
      {
         throw new NotImplementedException();
      }

      public override object ProvideValue(IServiceProvider serviceProvider)
      {
         return _instance ?? (_instance = new MyConverter());
      }
   }

Просмотр модели

   internal class MyViewModel : INotifyPropertyChanged
   {
      private bool _myProp1;
      private bool _myProp2;

      // Imagine the properties being altered at run-time

      public bool MyProp1
      {
         get { return _myProp1; }
         private set { _myProp1 = value; OnPropertyChanged(); }
      }

      public bool MyProp2
      {
         get { return _myProp2; }
         private set { _myProp2 = value; OnPropertyChanged(); }
      }

      public event PropertyChangedEventHandler PropertyChanged;

      private void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
   }

1 Ответ

0 голосов
/ 22 декабря 2018

Решение оказалось довольно простым простым , для свойства DependencyProperty используйте CoerceValueCallback вместо PropertyChangedCallback .Первый всегда вызывается, а последний - только если значение действительно изменилось.

Таким образом, в коде оно становится

  public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register(
          nameof(SetState),
          typeof(bool),
          typeof(CustomControl),
      new PropertyMetadata(false, null,
         (d, v) =>
         {
            ((CollapsibleColumnDefinition)d).IsExpanded = (bool)v;
            return v;
         }));

Я кратко попытался вручную обновить свойство зависимости (примечание ошибка ), но CoerceValueCallback делает именно то, что я хотел, и чище.

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