Нечетное поведение привязки в WPF

Я постараюсь объяснить это как можно лаконичнее. У меня есть 2 объекта, первый из которых мы назовем объектом A, имеющим свойство Id, а второй - объектом B, у которого есть свойство ParentId. Очевидная взаимосвязь состоит в том, что ParentId объекта B устанавливается равным свойству Id объекта A. Я использую шаблон MVVM, поэтому в модели просмотра у меня есть 2 ObservableCollections, одна из которых содержит объекты A, а другая - B. При построении модели просмотра я создаю и заполняю ObservableCollection ‹'A'> с именем ListItems. Мой xaml прост,

<StackPanel>
    <ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding ListItems}">
    </ListBox>

    <ComboBox SelectedValuePath="ParentId" SelectedValue="{Binding Path=ListItems/Id, Mode=OneWay}" ItemsSource="{Binding ComboItems}">
    </ComboBox>

    <Button Click="Button_Click" Content="Push Me"/>            
</StackPanel>

Как видите, SelectedValue поля со списком привязано к свойству Id текущего элемента ListItems. Таким образом, по сути, список и поле со списком находятся в основных деталях.

Если вы нажмете кнопку, она заполнит поле ObservableCollection ‹'B'> name ComboItems, которое, в свою очередь, заполнит поле со списком. Вот где начинается странность. Когда я запускаю программу, если единственное, что я делаю, это нажимаю кнопку, а затем после слов выбираю элемент в списке, поле со списком правильно выберет элемент из-за привязки SelectedValue. Но если я запускаю программу и сначала выбираю элемент в списке, а затем нажимаю кнопку, текущий элемент поля со списком не изменится с текущим элементом списка. Связь кажется разорванной навсегда. кто-нибудь знает, почему это произошло?

Пс. Если я установил ItemsSource в поле со списком до того, как установил SelectedValue / SelectedValuePath, привязка master / detail никогда не будет работать. Я знаю, что в xaml есть порядок, но это кажется немного хрупким. Так что, если у кого-то есть мнение по этому поводу, я все слышу.

Спасибо, Нейт

ИЗМЕНИТЬ -

При привязке SelectedValue он очень хрупкий. Если привязка работает, т.е. ничего не выбрали в списке, а затем заполнили поле со списком, если вы выберете элемент в поле со списком, привязка разорвется. Потратив много времени на это, я решил привязать SelectedItem. Эта привязка не нарушает ни одно из указанных мною ранее условий. Однако я хотел бы ответить на любые вопросы, почему привязка SelectedValue такая нелепая. Еще раз спасибо всем, что ответили или ответят.


person NastyNateDoggy    schedule 12.01.2010    source источник


Ответы (1)


Да, это проблема, с которой мы часто сталкиваемся.

Проблема в том, что после того, как свойство ItemsSource получит новое значение, привязка SelectedValue будет очищена. Отстой, и до сегодняшнего дня мы не нашли подходящего решения.

Вот несколько обходных путей:

  • Сбросьте привязку SelectedValue в коде, как только будет установлен новый ItemsSource. Вы можете сделать это в конвертере или где-нибудь, где вы знаете, что заменит привязку ItemsSource (например, событие DataContextChanged).

  • Вместо использования Binding на ItemsSource попробуйте использовать CollectionViewSource и фильтр. Поместите все свои элементы в объект CollectionViewSource и отфильтруйте элементы, когда поле со списком меняет значение.

  • Получите элемент вручную старомодным способом, когда ваш список выдает событие SelectionChanged.

Имейте в виду, что все решения в книге не самые красивые. Я бы выбрал вариант 2, это самый чистый ИМО;)

Надеюсь это поможет!

person Arcturus    schedule 12.01.2010
comment
Спасибо за Ваш ответ. Я вижу, как это применимо к порядку, в котором вы подключаете свои привязки в xaml, но я не уверен, что это применимо к моему первому вопросу, касающемуся выбора элемента в списке перед заполнением поля со списком. В этом сценарии ObservableCollection, к которому привязано поле со списком, никогда не заменяется, а заполняется только данными, поэтому я не понимаю / думаю, что привязка SelectedValue будет очищена. Спасибо, что ответили на мой второй вопрос. Дизайн кажется странным, но я думаю, что все в порядке. - person NastyNateDoggy; 12.01.2010
comment
Это действительно кажется странным. Возможно, ваша коллекция ListItems как-то пострадала. Похоже, что для IsSynchronizedWithCurrentItem установлено значение true, что означает, что он сопоставит CurrentItem вашей коллекции с SelectedItem, который изначально будет иметь значение NULL. Возможно, это сбросит выбранный вами элемент в вашем ListBox? - person Arcturus; 13.01.2010
comment
Я отметил это как ответ, хотя мне кажется, что он не полностью отвечает на мой вопрос. Прочтите мою правку выше, чтобы увидеть мое окончательное решение. - person NastyNateDoggy; 17.02.2010
comment
Спасибо .. Я поставлю ваш вопрос в избранное, потому что мы все еще ищем лучшее решение / объяснение этой проблемы. - person Arcturus; 17.02.2010