我使用prism v4和MEF来加载我的模块。我的模块包含一些视图(MVVM),它们由MEF自动加载到ItemsControl / NavigationRegion中。
这很好用,所有项目都显示在ItemControl中。但我不喜欢他们表现的顺序。一个模块可能包含多个项目,因此更改模块加载顺序本身是不够的。
如何对ItemsControl中的不同视图进行排序?是否有办法按某些财产对它们进行排序?
由于StockTraderRI示例中的属性,我使用棱镜V4,MEF和探索。
答案 0 :(得分:9)
这实际上是Prism4的结果。只需将ViewSortHintAttribute应用于您的视图:
[ViewSortHint("100")]
class FirstView : UserControl { }
[ViewSortHint("200")]
class SecondView : UserControl { }
区域上的默认排序比较器将选取此属性并相应地对视图进行排序。您可以将任何字符串放入属性中,但我倾向于使用中等大小的数字,这样我就可以轻松地在现有字符之间添加新视图。
答案 1 :(得分:2)
哦,dang,这比我预期的方式更容易:
您可以告诉区域经理如何对特定区域中的视图进行排序。您只需要为该地区提供比较功能。
此示例按非常愚蠢的值排序,即函数名称:
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;
}));
}
当然,应该使用一些比排序顺序的类名更有用的信息,但这应该很容易解决(我只是为所有可能添加到该区域的视图添加一个接口,提供一个值排序)。
答案 2 :(得分:1)
我很确定你正在寻找CollectionViewSource。 Bea提供了有关如何在链接中使用它的一些信息。
从MVVM的立场来看,这就是我在ViewModel中使用ICollectionView
的方式。 _scriptService.Scripts
属性被ObservableCollection<T>
包裹在ICollectionView
中,并返回到View。 _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;
}
}
}
下面是负责过滤的代码,它通过Prism中的DelegateCommand
进入,它位于同一个ViewModel中。
#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));
有关排序行为的更多信息可以在here找到,因为要记住一些性能方面的想法。
答案 3 :(得分:0)
您可以使用metadata或属性。这取决于你是否可以控制界面......
答案 4 :(得分:-2)
视图按添加顺序显示:
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView));
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView2));
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView3));
看起来像:
---- region-- | | view3 | | view2 | |查看|