Jeg bruger ofter ViewModel-first metoden når jeg anvender MVVM, dvs. jeg opretter først ViewModel instanser i koden og lader WPF om at finde de rette views for hver type af view model.

WPF har en DataTemplate som giver mulighed for at knytte views til mine view models:

<DataTemplate DataType="{x:Type vm:AlphaViewModel}">
  <view:AlphaView />
</DataTemplate> 

Lad os for eksemplet skyld antage at vi har en abstrakt GreekViewModel og et antal view models som nedarver fra denne, f.eks. AlphaViewModel, BetaViewModel, GammaViewModel, etc. Til hver view model har vi så et view, f.eks. AlphaView, BetaView, GammaView, etc. For hver view model anvender vi en DataTemplate for at knytte view model og view sammen. Lad os for ekspemplets skyld binde vores græske herligheder til en listbox.

<ListBox ItemsSource={Binding Greeks} />

Antallet af DataTemplates stiger hver gang vi tilføjer en ny view model, men for folk med god ordenssand (eller OCD) er der heldivis en nemmere måde at knytte view model og views sammen. 

Hvis man skeler til MVC kan man forstille sig at man kan udnytte en struktur som denne:

Hvis en view model, f.eks. AlphaViewModel, ligger i ViewModels folderen, så kan jeg forvente at et tilsvarende view, f.eks. AlphaView, findes i View folderen. For at få denne adfær kan vi benytte DataTemplateSelector. Det giver os mulighed for vælge en DataTemplate til hver view model i kode. 

public class GreekDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            var viewModelTypeName = item.GetType().FullName;
            var viewTypeName = viewModelTypeName.Replace("ViewModel", "View");
            var viewType = Type.GetType(viewTypeName);
            var template = new DataTemplate();
            template.VisualTree = new FrameworkElementFactory(viewType);
            return template;
        }
    }

GreekDataTemplateSelector ser på typen af item (i vores tilfælde en instans af en view model) og gætter på et navn for typen af viewet. I eksemplet vælger vi blot at erstattet ViewModel med View, dermed bliver "ViewModels.AlphaViewModel" til "View.AlphaView". Klassen FrameworkElementFactory bruges til at knytte view typen til en DataTemplate. Eksemplet kan nemt udvides, f.eks. skal der sker noget hvis et view ikke findes. Man kan søge efter flere forskellige navne, eller at der vælges et default view. Under alle omstændigheder skal koden opdateres med fejlcheck inden du sætter den i produktion.

Vores ListBox skal også lige opdateres for at få den ønskede effekt:

 

<ListBox ItemsSource={Binding Greeks} ItemTemplateSelector="{StaticResource GreekViewSelector}" />

 

 

Husk lige at oprette en instance af GreekDataTemplateSelector i Resources. DataTemplateSelector kan benyttes på mange forskellige klasser og giver mulighed for at udnytte hvordan koden er fysisk struktureret.