Как я могу получить 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;

Если данные связаны, я предполагаю, что будет иметь обновленное представление.

Другие вопросы по тегам