我正在为SL创建一种“导航面板”(实际上是一个ItemControl),并使用Regions允许每个模块将其链接添加到面板。
问题是模块加载不一致,因此面板中链接的顺序可能会根据模块加载顺序而改变。
限制模块订单是不可能的。
其他可行选项是绑定到ItemControl的区域的Views Collection的顺序,问题是ViewCollection非常有限,所以对它进行排序非常困难。
我错过了一个选项,你有什么想法吗?
由于 爱丽儿
答案 0 :(得分:7)
在Prism4中,您只需将ViewSortHintAttribute应用于您的视图:
[ViewSortHint("100")]
class FirstView : UserControl { }
[ViewSortHint("200")]
class SecondView : UserControl { }
区域上的默认排序比较器将选取此属性并相应地对视图进行排序。您可以将任何字符串放入属性中,但我倾向于使用中等大小的数字,这样我就可以轻松地在现有字符之间添加新视图。
答案 1 :(得分:3)
参考Sam的回答,首先要建立比较器。下面的一个也能够看到没有专门希望定位的视图。要将此比较器附加到必须进行排序的区域,您可以使用棱镜手册所引用的方式:
public partial class MainView : UserControl
{
public MainView( )
{
InitializeComponent( );
ObservableObject<IRegion> observableRegion = RegionManager.GetObservableRegion( ContentHost );
observableRegion.PropertyChanged += ( sender, args ) =>
{
IRegion region = ( (ObservableObject<IRegion>)sender ).Value;
region.SortComparison = CompareViews;
};
}
private static int CompareViews( object x, object y )
{
IPositionView positionX = x as IPositionView;
IPositionView positionY = y as IPositionView;
if ( positionX != null && positionY != null )
{
//Position is a freely choosable integer
return Comparer<int>.Default.Compare( positionX.Position, positionY.Position );
}
else if ( positionX != null )
{
//x is a PositionView, so we favour it here
return -1;
}
else if ( positionY != null )
{
//y is a PositionView, so we favour it here
return 1;
}
else
{
//both are no PositionViews, so we use string comparison here
return String.Compare( x.ToString( ), y.ToString( ) );
}
}
}
答案 2 :(得分:2)
至少在棱镜V4中,您可以告诉区域经理如何对特定区域中的视图进行排序。您只需要为该地区提供比较功能。
此示例按非常愚蠢的值排序,即函数名称:
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;
}));
}
当然,您应该使用比排序顺序的类名更有用的信息,但这应该很容易解决。
答案 3 :(得分:1)
这不是Prism地区的内容,但它很容易实现。
Damian Schenkelman发布了一个扩展方法,他创建了一个扩展方法,用于将一个区域添加到一个似乎运行良好的索引中。 http://blogs.southworks.net/dschenkelman/2009/03/14/how-to-add-a-view-to-a-region-in-a-particular-index-with-prism-v2/
希望这有帮助。
答案 4 :(得分:1)
我发现Sam的解决方案有效,但发现它在所有视图都添加到区域后执行排序,从而对视图进行了两次排序。
虽然它仍然是一个有效的解决方案,但在Prism讨论中阅读this帖子让我想到了在加载区域时,但在添加任何视图之前实现此方法的方法。
1 - 订阅RegionsChanged of Regions集合
我将它放在Shell ViewModel代码中,该代码与包含我要排序的区域的View相关联。每当IRegionManager导入被解析时,我订阅其Regions集合的CollectionChanged事件:
this._regionManager.Regions.CollectionChanged +=
new NotifyCollectionChangedEventHandler(Regions_CollectionChanged);
2 - 更改事件委托中区域的SortComparison
然后,只要Region集合更新,代理Regions_CollectionChanged
就会执行,并且会更改我所需区域的SortComparison
:
void Regions_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var o in e.NewItems)
{
IRegion region = o as IRegion;
if (region != null && region.Name == RegionNames.NavigationRegion)
{
region.SortComparison = CompareNavigatorViews;
}
}
}
}
3 - 定义CompareNavigatorViews委托
就我而言,我只是根据包含它们的程序集的标题对视图进行排序,您可以在此处实现自己的比较方法。请记住,您在此处收到的对象是视图而不是ViewModel。
private static int CompareNavigatorViews(object x, object y)
{
if (x == null)
if (y == null)
return 0;
else
return -1;
else
if (y == null)
return 1;
else
{
AssemblyInfo xAssemblyInfo = new AssemblyInfo(Assembly.GetAssembly(x.GetType()));
AssemblyInfo yAssemblyInfo = new AssemblyInfo(Assembly.GetAssembly(y.GetType()));
return String.Compare(xAssemblyInfo.Title, yAssemblyInfo.Title);
}
}
以防有人要求,AssemblyInfo类是我制作的实用程序类。要获得程序集的标题,您可以使用此函数:
string GetAssemblyTitle(Assembly assembly)
{
object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if (attributes.Length == 1)
{
return (attributes[0] as AssemblyTitleAttribute).Title;
}
else
{
// Return the assembly name if there is no title
return this.GetType().Assembly.GetName().Name;
}
}
希望这有助于某人!
答案 5 :(得分:0)
缺乏答案计数。我还没有找到Prism的解决方案。
相反,我使用MEF来解决这个问题。
我会写一篇博文并更新这个占位符。