Когда я отправил этот вопрос, я спешил, так как не хватало всего нескольких дней до очень важной демонстрации (раунд финансирования продукта).Поскольку я не мог понять, как подойти к проблеме с CollectionViewSource
, я решил попробовать решение, используя старый подход MultiValueConverter
, все время прекрасно понимая, что это заставит меня создать новый ObservableCollection
подмножества.значения коллекции, которые - согласно справочной странице C # для ObservableCollection<T>(IEnumerable<T>
) будут работать только односторонне, поскольку «элементы копируются в ObservableCollection<T>
».Я подумал, что было бы лучше показать, что представление заполнено из базы данных без отражения изменений в базе данных, чем вообще ничего не показывать.
Вообразите мое удивление, когда выяснилось, что страница руководстваздесь не совсем правильно: копируются только примитивные значения, сложные объекты передаются по ссылке в новый ObservableCollection<T>
!Это означает, что следующий фрагмент является полностью верным решением моей проблемы:
<ItemsControl ItemsSource="{Binding RootObjectCollection}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:CustomUserControl>
<local:CustomUserControl.SubsetCollection>
<MultiBinding Converter="{StaticResource SubsetEntryFromRootObjectIdSelectionConverter}">
<Binding Path="Value.SubsetIds" />
<Binding Path="DataContext.Database.SubsetCollection" RelativeSource="{RelativeSource AncestorType=UserControl}" />
</MultiBinding>
</local:CustomUserControl.SubsetCollection>
</local:CustomUserControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Важной частью здесь является сам MultiValueConverter
, который определяется как
public class SubsetEntryFromRootObjectIdSelectionConverter: IMultiValueConverter {
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
if (values[0] == null) // no reference ids contained
return new ObservableCollection<SubsetItem>();
if (!(values[0] is ObservableCollection<Guid>))
throw new InvalidOperationException("Value must be a collection of Guids.");
if (!(values[1] is ObservableCollection<KeyValuePair<Guid, SubsetItem>>))
throw new InvalidOperationException("Value must be a collection of SubsetItems.");
var selectedKeys = (ObservableCollection<Guid>)values[0];
var originalCollection = (ObservableCollection<KeyValuePair<Guid, SubsetItem>>)values[1];
var queryCollection = originalCollection.Where(kvp => selectedKeys.Contains(kvp.Key)).Select(kvp => kvp.Value);
// it seems that the man page is misleading and that this constructor indeed copies references, not objects
return new ObservableCollection<SubsetItem>(queryCollection);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
Так какРешение работает безупречно, я не реализовал тот, который предложен @ mm8 выше .Однако, с технической точки зрения, предлагаемое решение является прямым ответом на мой вопрос, тогда как мой, честно говоря, скорее обходной путь.Поэтому я приму ответ @ mm8 вместо моего.