Prisma para Silverlight: ¿Cómo mantener puntos de vista en un orden específico dentro de una región

StackOverflow https://stackoverflow.com/questions/2041765

Pregunta

Estoy creando una especie de "panel de navegación" (que en realidad es un ItemControl) para el NM y el uso de Regiones para permitir que cada módulo para añadir su vínculo con el panel.

El problema es que los módulos de carga es incompatible y, por tanto orden de enlaces en el panel puede cambiar de acuerdo con la orden de carga módulos.

La restricción de la orden de los módulos está fuera de la cuestión.

Otra opción viable es el orden colección Vistas de la región que se enganchan a la ItemControl, el problema es que ViewCollection es muy limitado, así que pedir es bastante difícil.

¿Me he perdido una opción, ¿tiene una idea?

Gracias Ariel

¿Fue útil?

Solución

En Prism4 sólo se aplican a la ViewSortHintAttribute sus puntos de vista:

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

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

El comparador de clasificación predeterminado en las regiones recogerá este atributo y ordenar las vistas en consecuencia. Usted puede poner cualquier cadena en el atributo, sino que tienden a utilizar los números de tamaño medio que me permiten poner fácilmente una nueva vista en entre los ya existentes.

Otros consejos

refiriéndose a la respuesta de Sam primero tiene que construir su comparador. El siguiente es también capaz de puntos de vista que no tienen un deseo dedicado a colocarse en. Para fijar este comparador a la región que tiene que ser resuelto puede utilizar una forma intruduced por el manual de prisma:

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

Por lo menos en prisma V4 no le puede decir el gerente de la región cómo ordenar las vistas en una región específica. Sólo tiene que proporcionar una función de comparación para la región.

En este ejemplo se ordena por un valor muy estúpida, el nombre de función:

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

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

Por supuesto, la región necesita ser conocida por el gestor de la región antes de poder establecer el SortComparison. Hasta ahora, la única solución que encontré para alcanzar este objetivo era aplazar para establecer la función de comparación con el despachador:

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

Por supuesto que debe usar alguna información más útil que el nombre de clase para el orden de clasificación, pero esto debe ser fácil de resolver.

Esto no está integrado en regiones Prism, sin embargo es de fácil implementación.

Damian Schenkelman ha publicado un método de extensión que creó para la adición de una región a un índice que parece funcionar bastante bien. http://blogs.southworks.net/dschenkelman/2009/03/14/how-to-add-a-view-to-a-region-in-a-particular -índice-con-prisma-v2 /

Espero que esto ayude.

He encontrado que la solución de Sam trabajó, pero descubrí que ejecuta la clase cuando todos los puntos de vista se han añadido a la región, para así ordenar las vistas en dos ocasiones.

A pesar de que sigue siendo una solución válida, la lectura este post en Prisma discusión me hizo pensar en una forma de implementar esto sólo cuando la región se ha cargado, pero antes de que los puntos de vista se han añadido todavía.

1 - suscribirse a la colección de las Regiones CollectionChanged

Me puse esto en el código Shell modelo de vista que es el asociado a la vista que contiene la región que desea ordenar. Siempre que la importación IRegionManager se ha resuelto Suscribo al evento CollectionChanged de su colección Regiones:

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

2 - Cambiar el SortComparison de la región en el delegado de eventos

A continuación, el delegado Regions_CollectionChanged ejecutará cada vez que se actualiza la colección Regiones y cambiará la SortComparison de mi región deseada:

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 - Definir el delegado CompareNavigatorViews

En mi caso, acabo de ordenar los puntos de vista por el título de la asamblea en la que están contenidos, puede implementar su propio método de comparación de aquí. Recuerde que los objetos que recibirá aquí están los puntos de vista y no los 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);
        }
}

Sólo en caso de que alguien le pregunta, la clase AssemblyInfo es una clase de utilidad que hice. Para obtener el título de un montaje que podría utilizar esta función:

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

Espero que esto ayude a alguien!

así como la falta de respuestas de conteo. No he encontrado una solución con Prism.

En lugar de ello he utilizado MEF para resolver esto.

Voy a escribir un blog en él y actualizar este marcador de posición.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top