Принудительное значение свойства зависимости, не переданного в цель или источник - PullRequest
1 голос
/ 28 февраля 2020

Проблема :

У меня есть пользовательское свойство зависимости (DP), называемое SelectedStoreString, в пользовательском элементе управления, называемое StorePicker. DP имеет PropertyChangedCallback и CoerceValueCallback. DP является двухсторонней привязкой к свойству в модели представления с тем же именем. Когда источнику присваивается значение в модели представления, вызывается CoerceValueCallback, и он возвращает окончательное значение, которое должно быть передано между целевым DP и источником в модели представления (оно может совпадать с назначенным значением или другой, если он был изменен в обработчике).

Затем значение отправляется на PropertyChangedCallback. Проблема в том, что приведенное значение, возвращаемое CoerceValueCallback, никогда не распространяется на цель или источник. Я использую POCOViewModels Dev Express WPF Framework, поэтому интерфейс INotifyPropertyChanged реализован в фоновом режиме.

Код :

//--------------------Poco view model--------------------------------------------------
  [POCOViewModel]
  public class FindOrdersViewModel
  {

    public virtual string SelectedStoreString { get; set; }


    public FindOrdersViewModel()
    {      
      SelectedStoreString = "48,49,55";
    }


    public static FindOrdersViewModel Create()
    {
      return ViewModelSource.Create(() => new FindOrdersViewModel());
    }

  }

//--------------------Dependency Property and its Handlers-----------------------------
    public static DependencyProperty SelectedStoreStringProperty = DependencyProperty.Register(nameof(SelectedStoreString), typeof(string), typeof(StorePicker), new FrameworkPropertyMetadata("",
                                                                                                                                                                                               FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                                                                                                                                                                               new PropertyChangedCallback(OnSelectedStoreStringChanged),
                                                                                                                                                                                               new CoerceValueCallback(CoerceSelectedStoreString),
                                                                                                                                                                                               false,
                                                                                                                                                                                               UpdateSourceTrigger.PropertyChanged));

    public string SelectedStoreString
    {
      get
      {
        return (string) GetValue(SelectedStoreStringProperty); // _selectedStoreString;
      }

      set
      {
        SetValue(SelectedStoreStringProperty, value);
      }
    }


    private static void OnSelectedStoreStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {

      StorePicker storePicker = d as StorePicker;

      if (d != null)
      {
        Dictionary<int, Store> sDct = new Dictionary<int, Store>();
        foreach (Store store in _stores)
          sDct.Add(store.STORE, store);
        string value = e.NewValue as string;

        if (value != null && value != "")
        {
          string[] strs = value.Split(',');
          foreach (string s in strs)
          {
            try
            {
              int x = Convert.ToInt32(s);
              Store outStore = sDct[x];
              if (outStore != null)
              {

                if (!outStore.InActive)
                {
                  storePicker.listBoxEdit1.SelectedItems.Add(outStore);

                }


              }
            }
            catch
            {
            }
          }
        }
      }
    }

    private static object CoerceSelectedStoreString(DependencyObject d, object v)
    {
      StorePicker storePicker = d as StorePicker;

      string finalSelectedStoresString = ""; //because the selectedstorestring may contain an Inactive store code we may need to adjust the string that was assigned
      if (d != null)
      {
        string[] storeCodes = ((string)v) == "" ? new string[0]: ((string)v).Split(',');
        foreach (string s in storeCodes) 
        {
          Store temp = _stores.Find(x => x.STORE == Convert.ToInt32(s) && !x.InActive);
          if (temp != null) 
          {
            finalSelectedStoresString += temp.STORE + ","; 
          }
        }

        if (finalSelectedStoresString != "")
        {
          finalSelectedStoresString = finalSelectedStoresString.Remove(finalSelectedStoresString.Length - 1, 1); //remove the ending comma from the string if it has one
        }

      }

      return finalSelectedStoresString;
    }

//------------------------------How the control is used in xml---------------------------------------
<ctl:StorePicker x:Name="StorePicker" Grid.Row="2" Grid.Column="1" Margin="10,-4,0,4" StoreType="All"  SelectedStoreString="{Binding SelectedStoreString,Mode=TwoWay}" IsAllStoresSelected="{Binding IsAllStoresSelected, Mode=TwoWay}"/>

Что я пробовал :

  • Вызов storePicker.SetCurrentValue (SelectedStoreStringProperty, e.NewValue as string) из PropertyChangedCallback. Это либо приводило к бесконечным l oop обратных вызовов, либо абсолютно ничего, если бы я использовал булеву переменную состояния, чтобы предотвратить бесконечное l oop. Но, тем не менее, не обновил привязку.

  • Установка режима привязки на Explicit и вызов storePicker.GetBindingExpression(SelectedStoreStringProperty).UpdateSource() и storePicker.GetBindingExpression(SelectedStoreStringProperty).UpdateTarget() для ручного обновления привязок. По-прежнему не обновлялись цель или источник.

  • Установка DP с помощью следующих методов (все из которых просто уничтожили привязку, тем самым победив цель): storePicker.SetValue(SelectedStoreStringProperty, e.NewValue as string), SelectedStoreString = e.NewValue as string

Что мне нужно :

Мне нужна возможность изменить значения свойства зависимости в выделенном фрагменте пользовательского элемента управления и передать эти значения в целевой DP и свойство источника в модели представления.

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