2012-03-22 2 views
1

У меня есть окно WPF со списком, связанное с obvserable коллекции (OC):Комбо-бокс теряет выбор после сбора изменений

<ComboBox Name="cbCombination" ItemsSource="{Binding Combinations}" 
       SelectedIndex="0" /> 

В другом месте, в объекте установить в качестве контекста данных:

public ObservableCollection<Combination> Combinations { get; set; } 

Комбинация переопределяет его ToString, и все персик: в раскрывающемся списке со списком отображаются все Комбинированные элементы в Combination OC. В поле выбора комбинированного окна отображается значение первого сочетания.

Теперь объект данных контекста должен изменить значение в его комбинации OC:

var combinationsList = CombinationsManager.CombinationsFor(someParam); 
    this.Combinations.Clear(); 
    foreach (var combination in combinationsList) 
     this.Combinations.Add(combination); 
    NotifyPropertyChanged(@"Combinations"); 

Это вызывает окно выбора поля со списка показывает пустую строку. (Выпадающее меню закрыто. Однако, когда я его выпадаю, он показывает правильные новые комбинации, поэтому -, связанный с обновленной коллекцией).

Я попытался захватить как SourceUpdated, так и (в моем случае) TargetUpdated events (отклонение установки SelectedIndex там), но мои обработчики событий не вызывались!

Так что мой вопрос: Как сделать WPF ComboBox обновить значение его окна выбора, когда наблюдаемая коллекция привязана к изменениям?

Update:

Я совершенно забыл упомянуть, и я не знаю, является ли это важно, но комбо-бокс в UserControl. XAML В UserControl выглядит следующим образом:

<UserControl x:Class="...CombinationsToolBar" 
     .... mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"> 
<ToolBarTray Name="toolBarTray1" > 
    <ToolBar Name="toolBar1"> 
     <ComboBox Name="cbCombination" 
     ItemsSource="{Binding Path=Combinations, NotifyOnSourceUpdated=True, 
                    IsAsync=True}" 
      SelectedIndex="0" IsEditable="False" 
      SelectionChanged="CbCombinationSelectionChanged" 
      SourceUpdated="CbCombinationSourceUpdated" 
      TargetUpdated="CbCombinationTargetUpdated"></ComboBox> 
    </ToolBar> 
</ToolBarTray> 

В коде UserControl в У меня есть точки останова на CbCombinationSelectionChanged, CbCombinationSourceUpdated и CbCombinationTargetUpdated.

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

Исходный обновленный и обновленный целевой объект не запускается - CbCombinationSourceUpdated и CbCombinationTargetUpdated не вызываются.

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

:(

ответ

3

Проблема заключается в вашем this.Combinations.Clear();
Когда вы его, он устанавливает SelectedItem = null и SelectedIndex = -1

Таким образом, вы должны установить выбор снова. Если у вас есть доступ к ComboBox, то просто написать это cbCombination.SelectedIndex = 0; после заполнения списка комбинаций.
Конечно, вы можете связать SelectedItem/SelectedIndex с некоторым свойством в коде.

BTW
Также не требуется вызвать NotifyPropertyChanged(@"Combinations"); после заполнения коллекции, потому что Combinations уже реализует INotifyPropertyChanged.

Update

Чтобы обнаружить, что ваш ObservableCollection был изменен, подписаться на CollectionChanged события в вашем UserControl кода позади. Убедитесь, что вы подписали до коллекция изменена!

Combinations.CollectionChanged += (s, e) => 
{ 
    if (cbCombination.Items.Count > 0) 
     cbCombination.SelectedIndex = 0; 
}; 

Другое предложение

подход выше работы, когда вам не нужно умнее логики, чем просто выбрать нулевой индекс в ComboBox. Но часто вам понадобится более сложная логика, чтобы выбрать какой-либо элемент. В этом случае вы можете добавить новое свойство модели:

public Combination SelectedCombination 
{ 
    get{ return _selectedCombination; } 
    set 
    { 
     _selectedCombination = value; 
     NotifyPropertyChanged("SelectedCombination"); 
    } 
} 

и связать это свойство к вашему выпадающий список:

<ComboBox Name="cbCombination" ItemsSource="{Binding Combinations}" 
      SelectedIndex="0" SelectedItem={Bindings SelectedCombination} /> 

В этом случае вы можете выбрать любой пункт при заполнении коллекции Комбинации, и это будет автоматически выбирается в combobox:

var combinationsList = CombinationsManager.CombinationsFor(someParam); 
this.Combinations.Clear(); 
foreach (var combination in combinationsList) 
    this.Combinations.Add(combination); 

if (Combinations.Count > 0) 
    SelectedCombination = Combinations[0]; 
+0

Спасибо, но: Я пытаюсь установить выбор снова, но как? Что должен просыпать мой код, который изменит SelectedItem и/или SelectedIndex? Вся моя проблема в том, что событие SourceUpdated в поле со списком не срабатывает! – Avi

+1

Вероятно, это срабатывает, но вы устанавливаете точку останова в сеттерах Комбинации, и это не будет срабатывать, если коллекция изменится, только если вы назначили ей другую коллекцию. Используйте selectindex, selectedvalue или selecteditem в коде. – Silvermind

+1

Я обновил ответ. Если этого еще недостаточно, чтобы решить проблему, дайте мне знать. – asktomsk

Смежные вопросы