CollectionViewSource CurrentItem

Я использую CollectionViewSource в модели представления диалога, которая имеет различные требования к фильтрации, которая работает нормально. Я также поддерживаю эквивалент выбранного элемента в свойстве (SelectedProject), и мне интересно, могу ли я/мог покончить с ним, поскольку View будет знать текущий элемент. Связывание данных выглядит следующим образом:

<ListView  
      ItemsSource="{Binding Projects.View}" 
      IsSynchronizedWithCurrentItem="True"
      SelectedItem="{Binding SelectedProject, Mode=TwoWay}">

Я использую setter для SelectedProject для облегчения модульного тестирования, и CurrentItem не представляется настраиваемым, насколько я могу видеть. Мне также нужно направить его на нужный объект, когда я захочу его использовать. OTOH, если SelectedProject избыточен, тогда я бы показал такое же уважение, как и любое другое избыточность, и удалю его.

Итак, как вы обычно относитесь к текущему элементу при использовании CollectionViewSource?

Ответ 1

Вы можете покончить с SelectedProject, но я бы возразил против него. Если у вас есть свойство в вашем коде, ясно, что вы делаете. Если у вас его нет, вам нужно будет сделать что-то вроде

CollectionViewSource.GetDefaultView(Projects.View).CurrentItem as Project

просто для взаимодействия с текущим проектом. Я ценю ясность над "встроенным". Кроме того, CurrentItem доступен только для чтения, поэтому, если вы когда-либо захотите выбрать элемент в ViewModel, это будет невозможно.

Ответ 2

Вам нужно понять, что SelectedItem из ListView не зависит от ItemsSource. Если вы используете CollectionViewSource или List или Array, выбранный элемент всегда будет представлять элемент этой коллекции.

Итак, чтобы ответить на ваш вопрос, почему ваш выбранный проект не настроен, я предлагаю вам проверить функциональность вашего сеттера на наличие ошибок. Хороший способ выяснить, содержит ли привязка какие-либо ошибки, - проверить наш вывод на наличие сообщений об ошибках связывания во время отладки.

ПРИМЕЧАНИЕ. Если ваш выбранный проект является тем же типом, что и элементы в вашем проекте CollectionViewSource, вам не нужно бросать его перед использованием (если только вы не сделали SelectedProject из типа объекта, а также объяснили проблему с настройкой).

РЕДАКТИРОВАТЬ: Извините, короткий ответ - нет, он не является избыточным. Наличие переменной, привязанной к текущему элементу, не является избыточным, если у вас есть тестирование. Хорошим примером является тестирование старой версии SelectedItem с помощью новой. Теперь, если вы ссылаетесь только на CollectionViewSource SelectedItem, это может быть слишком поздно для сравнения, но с вашей собственной переменной вы можете проверить логику, прежде чем устанавливать ее снова.

Ответ 3

В моем случае я пытался установить SelectedItem в ListBox, который ItemsSource был привязан к CollectionViewSource. Это грязно, потому что вам действительно нужно установить текущий элемент в CollectionViewSource, а не в ListBox.SelectedItem.... поэтому я создал метод расширения для обработки этого сценария для меня:

YourListBox.SetCurrentItemOnView<YourObjectType>(item);

... и определение метода расширения

public static void SetCurrentItemOnView<T>(this System.Windows.Controls.ListBox listBox, T item) where T : YourObjectType
{
    var view = listBox.ItemsSource as ListCollectionView;
    if (view == null) { return; }

    var itemToSelect = (from p in view.SourceCollection.OfType<T>()
                        where p.ID == item.ID
                        select p).FirstOrDefault();

    view.MoveCurrentTo(itemToSelect);
}

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