[英]How to sort views in an ItemsControl in Prism / MEF?
我用prism v4和MEF来加载我的模块。 我的模块包含一些视图(MVVM),它们由MEF自动加载到ItemsControl / NavigationRegion中。
这很好用,所有项目都显示在ItemControl中。 但我不喜欢他们表现的顺序。 一个模块可能包含多个项目,因此更改模块加载顺序本身是不够的。
如何在ItemsControl中对不同的视图进行排序? 是否有办法按某些财产对它们进行排序?
由于StockTraderRI示例中的属性,我使用棱镜V4,MEF和探索。
这实际上是Prism4的结果。 只需将ViewSortHintAttribute应用于您的视图:
[ViewSortHint("100")]
class FirstView : UserControl { }
[ViewSortHint("200")]
class SecondView : UserControl { }
区域上的默认排序比较器将获取此属性并相应地对视图进行排序。 您可以将任何字符串放入属性中,但我倾向于使用中等大小的数字,这使我可以轻松地在现有的数字之间添加新视图。
哦宕,这比我想象的更简单的方法 :
您可以告诉区域经理如何对特定区域中的视图进行排序。 您只需要为该地区提供比较功能。
这个例子按一个非常愚蠢的值排序,函数名称:
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;
}));
}
当然,应该使用一些比排序顺序的类名更有用的信息,但这应该很容易解决(我只是为所有可能添加到该区域的视图添加一个接口,提供一个值来排序)。
我很确定你正在寻找CollectionViewSource 。 Bea提供了有关如何在链接中使用它的一些信息。
从MVVM的立场来看,这就是我在ViewModel中使用ICollectionView
。 _scriptService.Scripts
属性是一个ObservableCollection<T>
被包装在ICollectionView
,并返回给View。 _view.Filter
用于过滤ICollection中的项目,从而更改View。 类似于输入'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));
有关排序行为的更多信息可以在这里找到,因为要记住一些性能想法。
您可以使用元数据或属性。 这取决于你是否可以控制界面......
视图按添加顺序显示:
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView));
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView2));
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView3));
看起来像:
---- region-- | | view3 | | view2 | | 查看|
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.