Странная проблема привязки к ComboBox, где отображаемое значение иногда отображается пустым - PullRequest
0 голосов
/ 02 июля 2010

При привязке к ComboBox я вижу странную проблему, когда отображаемое значение иногда отображается пустым. Однако этот случай повторяется и происходит во второй раз, когда диалог открывается из другой родительской формы. Если родительская форма закрыта и снова открыта, то при первом открытии дочернего диалога содержащийся WPF ComboBox правильно отображает свойство display. Если я затем закрою диалоговое окно и перезапущу его снова из той же родительской формы, ComboBox не показывает отображаемое значение, даже если я могу убедиться, что в моей ViewModel действуют те же связанные свойства.

<ComboBox ItemsSource="{Binding AvailableVehicles}"
          SelectedValuePath="Value"
          SelectedValue="{Binding SelectedVehicle, Mode=TwoWay}"
          DisplayValuePath="Value.Model" />

Чтобы объяснить структуру данных для моей ViewModel, в основном это просто класс, который предоставляет коллекцию AvailableVehicles, в которой хранятся объекты, похожие на тип Nullable <>, в котором он оборачивает объект Vehicle и предоставляет его через свойство Value. Каждый автомобиль имеет свойство Model и Cost.

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

Примечания:

  • Мне не удалось воспроизвести эту проблему в более простом примере с одним Window WPF.
  • Сценарий взаимодействия WinForms, в котором у меня есть родительская форма MDI и дочерние формы, в которых хранятся пользовательские элементы управления WPF на случай, если это может иметь значение.
  • Если установить для IsAsync значение True для привязок ItemsSource или SelectedValue, проблема больше не возникает.
  • Если вместо этого я превращаю DisplayValuePath в ItemsTemplate и в привязку внутри определенного DataTemplate, я помещаю конвертер, я заметил, что переданное значение равно нулю вместо ожидаемого значения.

Ответы [ 3 ]

2 голосов
/ 24 августа 2012

Я полагаю, что проблема была связана с объектом, связанным с SelectedValue, и объекты, которые были связаны с ItemsSource, были существенно разными экземплярами одних и тех же данных и оказались экземплярами классов, которые не перекрывали Equals или == оператор и тому подобное.Из того, что я испытал несколько раз сейчас, это то, что, поскольку SelectedValue или в некоторых случаях SelectedItem технически не равняется никаким объектам в связанном ItemsSource, тогда он игнорируется, и вы получите пустое значение, отображаемое в пользовательском интерфейсе.

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

Поэтому, когда я вижу этот симптом влюбой код, с которым я сталкиваюсь сейчас, моя первая вещь, которую нужно проверить, это связанные типы элементов и убедиться, что SelectedValue или SelectedItem действительно являются ReferenceEquals или Equals с одним из элементов в ItemsSource.А пока я просто расскажу об этом еще раз плохой поддержке разумной обратной связи об ошибках в WPF.

2 голосов
/ 14 апреля 2011

У меня была та же проблема, и единственным решением, которое я нашел, было создание двух свойств в моей ViewModel. Один как выбранное значение (Value), но он не привязан к ComboBox, а один для привязки (SelectedItem), который привязан к SelectedItem. В получателе SelectedItem я возвращаю Values.FirstOrDefault (x => x.Value == Value), а в установщике я устанавливаю значение по значению.Value. И наконец, когда значение было изменено в свойстве OnValueChanged, я уведомляю View об изменении SelectedItem (NotifyPropertyChanged ("SelectedItem")) ... ... 1001 *

0 голосов
/ 11 января 2019

Я боролся с этой проблемой около недели и до сих пор не знаю, что вызвало такое странное поведение комбобокса.

После повышения OnPropertyChanged против ItemsSource комбобокса ( @ Jeronimo the Black case), классический элемент управления combobox не может распознать, что SelectedItem все еще находится в базовой коллекции.Затем внутренние элементы управления устанавливают SelectedItem = NULL и пользовательский интерфейс отображается пустым.Ошибка состоит в том, что такое поведение, воспроизводимое на 50%, после переключения на другой объект или модель, может привести к самовосстановлению взаимосвязи между ItemsSource и SelectedItem.

В моем случае даже фильтрация ItemsSource вызвала эти ошибки.Обратите внимание, что свойство ParentRegionId имеет тип Nullable.

eg.1 без пробелов

    public IEnumerable CityDisplayList
    {
        get
        {
            if (_selectedCity != null && _selectedCity.ParentRegionId != null)
            {
                return ItemsSource.Where(x => x.ParentRegionId != null);
            }

            return Enumerable.Empty<TRegion>();
        }
    }

например.2 пробелы 50% (дополнительная фильтрация)

    public IEnumerable CityDisplayList
    {
        get
        {
            if (_selectedCity != null && _selectedCity.ParentRegionId != null)
            {
                return ItemsSource.Where(x => x.ParentRegionId != null && x.ParentRegionId == _selectedCity.ParentRegionId);
            }

            return Enumerable.Empty<TRegion>();
        }
    }

например.3 50% пробелов (IsAsync = True в операторе связывания)

ItemsSource="{Binding CityDisplayList, Mode=OneWay, IsAsync=True}"

Я поддерживаю идею @ jpierson , что лучше вообще не использовать SelectedItem, если ваша базовая коллекция и SelectedItem былисозданы в разных экземплярах классов или когда они имеют разные источники данных.Например, я использовал свойство зависимости, чтобы передать SelectedItem в UserControl.Однако ItemsSource был частью другого контекста UC.

Самый простой способ решить эту проблему - просто забыть о свойстве SelectedItem:

<ComboBox x:Name="cbxCity" ItemsSource="{Binding CityDisplayList}" DisplayMemberPath="RegionName"
              SelectedItem="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:ControlRegionCombobox}}, Path=SelectedCity}" />

и использовать «SelectedValue» + «SelectedValuePath»вместо:

<ComboBox x:Name="cbxCity" ItemsSource="{Binding CityDisplayList}" DisplayMemberPath="RegionName"
              SelectedValue="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:ControlRegionCombobox}}, Path=SelectedCity.Id}"
              SelectedValuePath="Id" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...