2010-11-23 9 views
4

Ich benutze prism v4 und MEF um meine Module zu laden. Meine Module enthalten eine Handvoll Ansichten (MVVM), die von MEF automatisch in eine ItemsControl/NavigationRegion geladen werden.Wie sortieren Sie Ansichten in einem ItemsControl in Prism/MEF?

Dies funktioniert gut, alle Elemente werden in ItemControl angezeigt. Aber ich mag die Reihenfolge nicht, in der sie zeigen. Ein Modul kann mehrere der Elemente enthalten, daher reicht es nicht aus, die Ladereihenfolge der Module zu ändern.

Wie kann ich die verschiedenen Ansichten in ItemsControl sortieren? Gibt es eine Möglichkeit, sie nach einer Eigenschaft zu sortieren?

Ich verwende Prisma V4, MEF und Exploration aufgrund von Attributen wie im StockTraderRI Beispiel.

+0

könnte dies nützlich sein: http://stackoverflow.com/questions/2041765/prism-for-silverlight-how-to-maintian-views-in-specific-order-inside-a-region –

Antwort

8

Dies ist tatsächlich in Prism4 gebacken. Wenden Sie einfach die ViewSortHintAttribute auf Ihre Ansichten:

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

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

Die Standardsortier Vergleich zu den Regionen wird dieses Attribut aufheben und die Ansichten sortieren entsprechend. Sie können eine beliebige Zeichenfolge in das Attribut einfügen, aber ich neige dazu, mittelgroße Zahlen zu verwenden, die es mir erlauben, leicht eine neue Ansicht zwischen vorhandenen zu setzen.

+0

Eine weitere angehängte Eigenschaft auf 'RegionManager' wäre für mich viel sinnvoller. Attribute sind Konstanten zur Kompilierungszeit und können in XAML nicht angegeben werden. Dies ist für einige Arten von Sichten hilfreich, für die sonst kein Code-Behind erforderlich wäre. Zum Beispiel würde ein Menübereich Menüelemente enthalten. Normalerweise würden Sie einfach ein 'MenuItem' erstellen und es der Region hinzufügen, aber Sie können nicht, wenn Sie die Sortierreihenfolge angeben möchten! –

+2

Im Anschluss an meinen obigen Kommentar habe ich dieses Problem selbst gelöst, indem ich eine angefügte Eigenschaft 'Sort.Order' (Typ' int') definiert habe, dann ein 'SortingRegionBehavior', das es benutzt. Schließlich registriert mein Bootstrapper dieses Verhalten als Standard, so dass alle Regionen es bekommen. Die einzige Einschränkung, die ich bisher gefunden habe, ist, dass Änderungen an der 'Sort.Order'-Eigenschaft nach der Tat nicht berücksichtigt werden, aber ich bin mir ziemlich sicher, dass ich das für mein Regionsverhalten unterstützen kann, wenn ich es jemals brauche . –

1

Ich bin mir ziemlich sicher, dass Sie nach dem CollectionViewSource suchen. Bea gibt einige Informationen darüber, wie man es in der Verbindung verwenden kann.

Von einer MVVM-Haltung aus verwende ich die ICollectionView in meinem ViewModel. Die _scriptService.Scripts Eigenschaft ist eine ObservableCollection<T>, die in einem ICollectionView eingewickelt wird, das zu der Ansicht zurückgegeben wird. Die _view.Filter wird verwendet, um Elemente innerhalb der ICollection herauszufiltern, wodurch die Ansicht geändert wird. Ähnlich wie "acc" eingeben und alle Einträge sehen, die in Ihrer Liste mit "acc" beginnen.

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

Unten ist der Code, der Pflege der Filterung erfolgt, und über eine innerhalb DelegateCommand Prism kommt, dies in der gleichen Ansichtsmodell befindet.

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

Mit der Basisfunktionalität an Ort und Stelle und die Nutzung der ICollectionView Sie Ihre Sortierung anwenden können wie folgt ....

_view.SortDescriptions.Add(new SortDescription("PropertyName", direction)); 

Weitere Informationen über das Sortierverhalten kann here gefunden werden, da sind einige Performance-Gedanken zu beachten.

+0

Also, wie würde Ich benutze es in Prisma/MVVM? – Sam

+1

@Sam Bea geht durch den Link oben. Die Verwendung der CollectionViewSource ist für Prism nicht per se anwendbar, entspricht jedoch dem MVVM-Muster. Posted ein Beispiel, wie ich es benutze. –

+0

Aaron, sieht gut aus, ich werde es überprüfen und als Antwort markieren, sobald ich es funktioniert habe, danke !! – Sam

0

Sie könnten entweder metadata oder Eigenschaften verwenden. Es hängt davon ab, ob Sie die Kontrolle über die Schnittstelle haben oder nicht ...

+0

Ich wollte lieber * wie * sortieren, nicht * nach was *. Wenn ich ein Beispiel dafür finde, wie sortiert werden kann, werde ich keine Sorge haben, eine Eigenschaft oder Metadaten zu finden, die ich zum Sortieren verwenden möchte. – Sam

+1

Ahhh, ich weiß sehr wenig über WPF, also kann ich nicht anders! – Tim

1

Oh dang, das war Weg einfacher als ich erwartet hatte:

Sie können die Region Manager sagen, wie sich die Ansichten in einem bestimmten sortieren Region. Sie müssen lediglich eine Vergleichsfunktion für die Region bereitstellen.

Dieses Beispiel sortiert durch einen sehr dummen Wert, die Funktionsnamen:

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

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

Natürlich ist die Region muss die Region Manager bekannt sein, bevor Sie die SortComparison einstellen. Bisher ist die einzige Lösung fand ich dies zu erreichen, war zu verschieben die Vergleichsfunktion, um den 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; 
    })); 
} 

Natürlich sollte man einige weitere nützliche Informationen als der Klassenname für die Sortierreihenfolge verwenden, aber dies sollte leicht zu lösen sein (ich werde nur eine Schnittstelle zu allen Ansichten hinzufügen, die zu dieser Region hinzugefügt werden können, die einen Wert zum Sortieren bereitstellen).

+2

Ich habe soeben eine Antwort hinzugefügt http://stackoverflow.com/questions/2041765/prism-for-silverlight-how-to-maintain-views-in-a-specific-order-inside-a-region/4452910#4452910 was in diesem Zusammenhang auch interessant sein kann. – PVitt

-2

Ansichten in der Reihenfolge angezeigt, sie hinzugefügt werden:

RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView)); 
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView2)); 
RegionManager.RegisterViewWithRegion("ListRegion", typeof(ListView3)); 

wird wie folgt aussehen:

---- region-- | | Ansicht3 | | view2 | | Ansicht |