Как отсортировать представления в ItemsControl в Prism / MEF? - PullRequest
5 голосов
/ 23 ноября 2010

Я использую Prism v4 и MEF для загрузки своих модулей.Мои модули содержат несколько представлений (MVVM), которые автоматически загружаются в ItemsControl / NavigationRegion с помощью MEF.

Это прекрасно работает, все элементы отображаются в ItemControl.Но мне не нравится порядок, в котором они показывают.Один модуль может содержать несколько элементов, поэтому изменение порядка загрузки модуля само по себе недостаточно.

Как можно отсортировать различные представления в ItemsControl?Есть ли способ отсортировать их по какому-либо свойству?

Я использую призму V4, MEF и исследование из-за атрибутов, как в примере StockTraderRI.

Ответы [ 5 ]

10 голосов
/ 17 декабря 2010

Это на самом деле запекается в Prism4.Просто примените ViewSortHintAttribute к вашим представлениям:

[ViewSortHint("100")]
class FirstView : UserControl { }

[ViewSortHint("200")]
class SecondView : UserControl { }

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

2 голосов
/ 26 ноября 2010

О черт, это было в порядке проще, чем я ожидал:

Вы можете указать менеджеру региона, как сортировать представления в определенном регионе.Вам просто нужно предоставить функцию сравнения для региона.

Этот пример сортирует по очень глупому значению, имени функции:

private static int CompareViews(object x, object y)
{
  return String.Compare(x.ToString(), y.ToString());
}

this._regionManager.Regions["MyRegion"].SortComparison = CompareViews;

Конечно, регион должен быть известенрегиональный менеджер, прежде чем вы сможете установить SortComparison.До сих пор единственным решением, которое я нашел для достижения этой цели, было отложить установку функции сравнения с помощью Dispatcher:

private readonly IRegionManager _regionManager;

[ImportingConstructor]
public ShellViewModel(IRegionManager regionManager)
{
  this._regionManager = regionManager;
  Dispatcher dp = Dispatcher.CurrentDispatcher;
  dp.BeginInvoke(DispatcherPriority.ApplicationIdle, new ThreadStart(delegate
  {
    if (this._regionManager.Regions.ContainsRegionWithName("MyRegion"))
      this._regionManager.Regions["MyRegion"].SortComparison = CompareViews;
  }));
}

Конечно, для порядка сортировки нужно использовать более полезную информацию, чем имя класса, ноэто должно быть легко решено (я просто добавлю интерфейс ко всем представлениям, которые могут быть добавлены в этот регион, которые предоставляют значение для сортировки).

1 голос
/ 23 ноября 2010

Я почти уверен, что вы ищете CollectionViewSource . Bea предоставляет некоторую информацию о том, как использовать ее в ссылке.

С позиции MVVM так я использую ICollectionView в моей ViewModel. Свойство _scriptService.Scripts - это ObservableCollection<T>, заключенное в ICollectionView, которое возвращается в представление. _view.Filter используется для фильтрации элементов в ICollection, тем самым изменяя представление. Аналогично вводу 'acc' и отображению всех элементов, которые начинаются с 'acc' в вашем списке.

    public class ScriptRepositoryViewModel : AViewModel
    {
        private readonly IUnityContainer _container;
        private readonly IScriptService _scriptService;
        private readonly IEventAggregator _eventAggregator;

        private ICollectionView _view;

        public ScriptRepositoryViewModel(IUnityContainer container, IScriptService scriptService, IEventAggregator eventAggregator)
        {
            _container = container;
            _scriptService = scriptService;
            _eventAggregator = eventAggregator;
        }

        public ICollectionView Scripts
        {
            get 
            {
                if (_view == null)
                {
                    _view = CollectionViewSource.GetDefaultView(_scriptService.Scripts);
                    _view.Filter = Filter;
                }

                return _view;
            }
        }
     }

Ниже приведен код, который заботится о фильтрации и входит через DelegateCommand в Prism, он находится в той же модели представления.

#region SearchCommand
public DelegateCommand<object> SearchCommand { get; private set; }

private String _search = String.Empty;
private void Search(object commandArg)
{
    _search = commandArg as String;
    _view.Refresh();
}

public bool Filter(object arg)
{
    bool usingPrefix;

    IScript script = arg as IScript;
    if (script.FileType == ConvertPrefixToFileType(_search, out usingPrefix))
    {
        if (_search.Length == 2)
            return true;
        else
            return CheckProperties(script, usingPrefix);
    }
    else
    {
        if (usingPrefix)
            return false;
        else
            return CheckProperties(script, usingPrefix);
    }
}

Имея базовую функциональность и используя ICollectionView, вы можете применить свою сортировку следующим образом ...

_view.SortDescriptions.Add(new SortDescription("PropertyName", direction));

Более подробную информацию о порядке сортировки можно найти здесь , так как есть некоторые соображения по поводу производительности, которые нужно учитывать.

0 голосов
/ 03 декабря 2010

Представления отображаются в порядке их добавления:

RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView));
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView2));
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView3));

будет выглядеть так:

---- region-- | | view3 | | view2 | | просмотр |


0 голосов
/ 23 ноября 2010

Вы можете использовать либо метаданные , либо свойства.Это зависит от того, есть ли у вас контроль над интерфейсом или нет ...

...