Как я могу получить CollectionView, который определен в XAML
Я хотел привязать к ObservableCollection
в XAML, а также применить группировку там. В принципе это работало нормально.
<UserControl.Resources>
<CollectionViewSource x:Key="cvs" Source="{Binding Path=TestTemplates}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Title"/>
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="TestCategory"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</UserControl.Resources>
Затем выражение привязки данных стало ItemsSource="{Binding Source={StaticResource ResourceKey=cvs}}"
вместо ItemsSource="{Binding Path=TestTemplates}"
,
Сначала все казалось крутым, пока я не захотел обновить интерфейс в представлении модели. Проблема в том, что CollectionViewSource.GetDefaultView(TestTemplates)
возвратил другое представление, чем из XAML, где была применена группировка. Таким образом, я не мог установить выбор или сделать что-нибудь полезное с ним.
Я мог бы исправить это, связав список снова непосредственно со свойством модели представления и установив группировку в коде. Но я не так доволен этим решением.
private void UserControlLoaded(object sender, RoutedEventArgs e)
{
IEnumerable source = TemplateList.ItemsSource;
var cvs = (CollectionView)CollectionViewSource.GetDefaultView(source);
if (cvs != null)
{
cvs.SortDescriptions.Add(new SortDescription("Title", ListSortDirection.Ascending));
cvs.GroupDescriptions.Add(new PropertyGroupDescription("TestCategory"));
}
}
Я предполагаю, что причина этого уже приведена здесь Джоном Скитом.
Тем не менее, я ожидаю, что должен быть способ получить правильное представление. Я ошибся?
3 ответа
Нашел способ, основываясь на ответе J. Lennon. Если я передаю что-то, что имеет доступ к ресурсам с моей командой, то я могу посмотреть CollectionViewSource
там.
В XAML (CollectionViewResource
как указано выше):
<Button Command="{Binding Command}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}">Do it!</Button>
И в коде ВМ:
private void Execute(object parm)
{
var fe = (FrameworkElement)parm;
var cvs = (CollectionViewSource)fe.FindResource("cvs");
cvs.View.Refresh();
}
Execute
это тот, который предоставляется RelayCommand.
Это ответило бы на вопрос, но мне это не очень нравится. Мнения?
Я имею тенденцию просто выставлять представление коллекции от VM, а не иметь представление, определяющее это:
public ICollection<Employee> Employees
{
get { ... }
}
public ICollectionView EmployeesView
{
get { ... }
}
Таким образом, ваша виртуальная машина имеет полный контроль над тем, что выставлено на просмотр. Например, он может изменить порядок сортировки в ответ на какое-либо действие пользователя.
Вы не могли бы просто сделать это?
var _viewSource = this.FindResource("cvs") as CollectionViewSource;
Если данные связаны, я предполагаю, что будет иметь обновленное представление.