EventToCommand - как предотвратить рекурсивные / реентерабельные вызовы при обработке выборки. - PullRequest
0 голосов
/ 20 августа 2011

См. Код макета здесь

Я создаю интерактивную страницу поиска, которая выбирает данные в качестве критериев ввода пользователя.Короче говоря, у меня есть несколько комбо-боксов, в которых их SelectionChanged событие обрабатывается EventToCommand.

EventToCommand вызывает метод на моем ViewModel, который, помимо прочего, изменяет выбранноепредмет для нескольких комбо-боксов.Конечно, это вызывает EventToCommand, и весь процесс происходит снова ... и снова ... и снова ...

Так что мой вопрос, есть ли способ сделать привязку к EventToCommandверно OneWayToSource чтобы обновление из источника не вызывало событие?

1 Ответ

0 голосов
/ 29 марта 2012

Метод 1, приведенный ниже, показывает, возможно, ценную иллюстрацию метода, но большинство приложений, вероятно, лучше всего подойдет по Методу 2.

Метод 1

В качестве первого подхода я принял подход, предложенный jberger. Однако, поскольку я полагаюсь на значения, содержащиеся в аргументах события, и хочу сохранить разделение задач между моим View и ViewModel в соответствии с целями и принципами MVVM, я поместил эту добавленную логику в свой программный код, чтобы сохранить зависимость в Код вида.

Я использовал хэш содержимого AddedItems в аргументах событий, чтобы отличать «повторные» вызовы из-за привязки свойства другого ComboBox от новых вызовов метода обработки событий из-за взаимодействия с пользователем.

    int hashCode = 0;
    private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
      string addedItemsCatString = "";
      foreach (string item in e.AddedItems) addedItemsCatString += item;
      int newHashCode = addedItemsCatString.GetHashCode();
      if ( newHashCode == hashCode) return;
      hashCode = newHashCode;

      // execute Command code here
    }

Конкатенация содержимого AddedItems не является строго необходимой для ComboBox, где одновременно может быть выбран только один элемент, но он допускает аналогичный подход для элементов управления с множественным выбором.

Метод 2

Поскольку я не был полностью удовлетворен методом 1, я продолжал думать о лучшем решении. Мне пришло в голову понимание, что я действительно хотел выполнить команду только один раз, основываясь на взаимодействии с пользователем. То, что похоже на хороший флаг, чтобы отличить событие SelectionChanged из-за взаимодействия с пользователем от события из-за привязки свойства, - это фокус клавиатуры.

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
  if (!(sender as FrameworkElement).IsKeyboardFocusWithin) return;

      // execute Command code here

}

Таким образом, приведенный выше тест может быть лучшим решением для большинства случаев, в том числе для случаев, когда событие SelectionChanged инициируется другим режимом ввода, в котором не задействованы какие-либо селекторы GUI, например сочетанием клавиш или внутренним изменением состояние вашей программы - или в любом месте, где вы можете выполнить команду, что приведет к срабатыванию нескольких событий SelectionChanged, если вы использовали несколько элементов управления для управления настройкой. Свойство экземпляра FrameworkElement.IsKeyboardFocused и статический метод Keyboard.Focus (frameworkElementInstance) также могут быть полезны для различных элементов управления или сценариев.

Подробнее о фокусе клавиатуры можно узнать на MSDN здесь .

...