2010-12-04 33 views
2

J'ai un contrôle utilisateur réutilisable avec un viewmodel derrière. J'essaie de basculer entre différentes vues des mêmes données. Essaie actuellement d'utiliser une propriété Mode sur la machine virtuelle pour accomplir ceci.Deux vues du même ViewModel dans un contrôle utilisateur

J'ai créé un DataTemplateSelector comme ceci:

<UserControl x:Class="MyUserControl"> 
    <UserControl.Resources> 
     <DataTemplate x:Key="ColumnTemplate"> 
      <StackPanel> 
       <Label Text="{Binding Name}"></Label> 
       <Label Text="{Binding Address}"></Label> 
       <Label Text="{Binding Occupation}"></Label> 
      </StackPanel> 
     </DataTemplate> 
     <DataTemplate x:Key="AvatarTemplate"> 
      <StackPanel> 
       <Image Source="{Binding ProfilePicture}"></Image> 
       <Label Text="{Binding Name}"></Label> 
      </StackPanel> 
     </DataTemplate> 
    <local:DisplayTemplateSelector ColumnTemplate="{StaticResource ColumnTemplate}" AvatarTemplate="{StaticResource AvatarTemplate}" x:Key="displayTemplateSelector" /> 
</UserControl.Resources> 
<Grid> 
    <ContentControl Name="cpDisplay" Content="{Binding}" ContentTemplateSelector="{StaticResource displayTemplateSelector}" /> 
</Grid> 
</UserControl> 

Avec la classe:

class DisplayTemplateSelector : DataTemplateSelector 
{ 

    public DataTemplate ColumnTemplate {get;set;} 

    public DataTemplate AvatarTemplate {get;set;} 

    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     MainViewModel vm = (MainViewModel)item; 

     switch (vm.Mode) 
     { 
      case MainViewModel.DisplayMode.Column: 
       return ColumnTemplate; 
      case MainViewModel.DisplayMode.Avatar: 
       return AvatarTemplate; 
      default: 
       return AvatarTemplate; 
     } 
    } 

} 

Cette usercontrol se trouve dans MyWindow:

<Grid> 
    <controls:MyUserControl x:Name="MyUserControl" DataContext="{Binding}" Margin="0"/> 
</Grid> 

Ce qui est instancié avec mon viewmodel :

MyWindow w = new MyWindow(_vm); 
w.Show(); 

Le problème que j'ai est que item est nul pendant MainViewModel vm = (MainViewModel)item. C'est comme si j'essayais de définir le datatemplate en fonction des données, avant que les données ne soient liées?

Est-il possible de choisir le modèle de données souhaité non basé sur l'objet de données - mais comme une propriété ou similaire sur la commande usercontrol?

Répondre

2

Il y a plusieurs façons, mais voici quelques:

<!-- assumes you have a data template selector implementation available as resource MyContentSelector --> 
<ContentControl Content="{StaticResource MainViewModel}" ContentTemplateSelector="{StaticResource MyContentSelector}"/> 

ou:

<!-- assumes you have appropriate boolean properties on your VM --> 
<Grid> 
    <ContentControl Content="{StaticResource MainViewModel}" ContentTemplate="{StaticResource column}" Visibility="{Binding IsColumnVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/> 
    <ContentControl Content="{StaticResource MainViewModel}" ContentTemplate="{StaticResource avatar}" Visibility="{Binding IsAvatarVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/> 
</Grid> 
+0

Merci les gars, mais cela signifie que le seul moyen de contrôler le mode de l'interface utilisateur est de définir une propriété sur le ViewModel? Si oui, qu'il en soit ainsi. – DaveO

+0

La deuxième solution a conduit à ce que j'ai fait à la fin. – DaveO

0

Ok, a finalement obtenu ce au travail comment j'ai eu besoin en utilisant une propriété sur le usercontrol et du code derrière:

public enum DisplayMode 
    { 
     Column, 
     Avatar 
    } 

    public DisplayMode Mode { get; set; } 


    public MyUserControl() 
    { 
     InitializeComponent(); 
     Mode = DisplayMode.Avatar; 
    } 

    private void MyUserControl_Loaded(object sender, RoutedEventArgs e) 
    { 
     switch (Mode) 
     { 
      case DisplayMode.Column: 
       cpDisplay.ContentTemplate = (DataTemplate)this.Resources["ColumnTemplate"]; 
       cpDisplay.ApplyTemplate(); 
       break; 
      case DisplayMode.Avatar: 
       cpDisplay.ContentTemplate = (DataTemplate)this.Resources["AvatarTemplate"]; 
       cpDisplay.ApplyTemplate(); 
       break; 
     } 
    } 

J'ai supprimé le code DataTemplateSelector et simplement définir les DataTemplates et utilisés:

<ContentPresenter Name="cpDisplay" Content="{Binding}" />