3

我正在为 SL 创建一种“导航面板”(实际上是一个 ItemControl),并使用区域来允许每个模块将他的链接添加到面板。

问题是模块加载不一致,因此面板中的链接顺序可能会根据模块加载顺序而改变。

限制模块顺序是不可能的。

其他可行的选项是绑定到 ItemControl 的区域的 Views Collection 的顺序,问题是 ViewCollection 非常有限,因此很难排序。

我错过了一个选项,你有什么想法吗?

谢谢爱丽儿

4

6 回答 6

7

在 Prism4 中,您只需将 ViewSortHintAttribute 应用于您的视图:

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

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

区域上的默认排序比较器将获取此属性并相应地对视图进行排序。您可以将任何字符串放入属性中,但我倾向于使用中等大小的数字,这样我就可以轻松地在现有视图之间放置一个新视图。

于 2010-12-25T23:51:55.070 回答
3

参考 Sam 的回答,您首先必须建立您的比较器。下一个也能够查看没有专门希望定位的视图。要将此比较器附加到必须排序的区域,您可以使用 prism 手册中介绍的方法:

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( ) );
        }
    }
}
于 2010-12-15T17:22:53.850 回答
2

至少在 prism 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;
  }));
}

当然,您应该使用一些比类名更有用的信息来进行排序,但这应该很容易解决。

于 2010-11-26T13:40:21.847 回答
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/

希望这可以帮助。

于 2010-01-13T16:02:39.350 回答
1

我发现 Sam 的解决方案有效,但发现它在所有视图都添加到该区域时执行排序,因此对视图进行了两次排序。

虽然它仍然是一个有效的解决方案,但阅读Prism 讨论中的这篇文章让我想到了一种在加载区域时实现它的方法,但在添加任何视图之前。

1 - 订阅 Regions 集合的 CollectionChanged

我将它放在 Shell ViewModel 代码中,该代码与包含我要排序的区域的视图相关联。每当解决 IRegionManager 导入时,我都会订阅其 Regions 集合的 CollectionChanged 事件:

this._regionManager.Regions.CollectionChanged +=
        new NotifyCollectionChangedEventHandler(Regions_CollectionChanged);

2 - 在事件委托中更改区域的 SortComparison

然后,每当 Regions 集合更新时,委托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 委托

在我的例子中,我只是按包含它们的程序集的标题对视图进行排序,您可以在此处实现自己的比较方法。请记住,您将在此处收到的对象是 Views 而不是 ViewModels。

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;
    }
}

希望这对某人有帮助!

于 2013-03-12T22:37:44.097 回答
0

以及缺乏答案计数。我还没有找到 Prism 的解决方案。

相反,我使用 MEF 来解决这个问题。

我会在上面写一篇博文并更新这个占位符。

于 2010-01-14T19:20:08.870 回答