2010-12-13 57 views
1

J'ai une classe User et une classe Author qui étend l'utilisateur. J'ai un ObservableCollection < L'utilisateur > étant affiché dans un ListBox. Pour cela, j'ai un DataTemplate pour afficher chaque élément et un autre pour afficher chaque élément sélectionné. J'ai également une colonne de TextBoxes qui sont liés aux propriétés de la propriété ListBox.SelectedItem. Jusqu'ici tout va bien.Dois-je utiliser des DataTemplates ou un UserControl pour afficher différents contrôles pour les classes étendues?

Pour l'instant, j'affiche des contrôles supplémentaires dans la colonne et DataTemplates si l'utilisateur sélectionné est un auteur et tout fonctionne bien, mais je triche. J'ai ajouté une propriété booléenne IsAuthor dans la classe User afin que je puisse lier à elle et déterminer si un utilisateur était un auteur. Je sais que c'est faux, mais je ne pouvais pas trouver d'autre moyen de le faire, alors ma première question est de savoir comment afficher les classes étendues différemment de la classe de base? J'ai essayé un DataTemplate différent pour le type Auteur, mais cela n'a jamais fonctionné ... peut-être parce que la collection était de type Utilisateur? La deuxième question est de devrais-je avoir tous les nombreux contrôles TextBox dans la colonne dans un contrôle UserControl et modifier les contrôles liés à la visibilité de l'auteur, ou en quelque sorte les mettre dans un DataTemplate et en créer un pour chaque type? J'utilise actuellement la première méthode et le problème est que chaque contrôle lié à une propriété Auteur lance des erreurs (je peux les voir dans la fenêtre de sortie dans Visual Studio) lorsque l'élément actuellement sélectionné n'est pas un auteur.

Répondre

2

J'ai une configuration similaire qui utilise des modèles de données et cela fonctionne très bien avec les classes héritées. C'est comme ça que je l'ai fait.

<ListBox Name="UserList" ItemsSource="{Binding Path=Users}" 
     ItemTemplate="{StaticResource ShowUserName}" 
     SelectedItem="{Binding Path=SelectedUser, Mode=TwoWay}"> 
</ListBox> 
<ContentControl Content="{Binding ElementName=UserList, Path=SelectedItem}"/> 

Dans la section Window.Resources je les DataTemplates suivants:

<DataTemplate x:Key="ShowTime" DataType="TestApp.User"> 
    <TextBlock Text="{Binding Path=Name}" HorizontalAlignment="Center"/> 
</DataTemplate> 
<DataTemplate DataType="{x:Type local:User}"> 
    <StackPanel Margin="10"> 
    <TextBlock Text="{Binding Path=Name}"/> 
    <TextBlock Text="{Binding Path=Age}"/> 
    </StackPanel> 
</DataTemplate> 
<DataTemplate DataType="{x:Type local:Author}"> 
    <StackPanel Margin="10"> 
    <TextBlock Text="{Binding Path=Name}"/> 
    <TextBlock Text="{Binding Path=Age}"/> 
    <TextBlock Text="{Binding Path=FirstTitle}"/> 
    </StackPanel> 
</DataTemplate> 

Le premier modèle est ce qui sera affiché dans la liste elle-même. Nous le référençons par clé dans la propriété ItemTemplate de la zone de liste. Les deux autres modèles de données sont utilisés par le contrôle de contenu lors de la détermination des éléments à afficher pour l'élément sélectionné. Lorsque l'élément sélectionné est juste un utilisateur, le DataTemplate utilisateur sera affiché, si un auteur est sélectionné, l'auteur DataTemplate sera affiché.

Le type local: Author fait référence au type de classe. local doit être déclaré dans vos déclarations d'espace de noms. N'oubliez pas que ceci est mon espace de nom, vous devrez spécifier celui que vous utilisez. Et bien sûr, les modèles de données ne sont que des exemples basiques, probablement que vous voudrez faire quelque chose de plus adapté à votre application.

Cependant, il peut être irritant de devoir définir deux modèles de données distincts qui sont presque exactement les mêmes pour vos deux classes. Bien que vous puissiez certainement. Je le fais dans ma propre application (pas dans cet exemple), parce que ce que je veux afficher pour chaque type est très différent. Donc, ce qui pourrait être utile est de créer un DataTemplate commun pour toutes les propriétés de l'utilisateur, et d'étendre simplement ce DataTemplate pour les auteurs. Si vous voulez faire que vous pouvez configurer vos modèles ainsi:

<DataTemplate x:Key="UserTemplate"> 
    <!-- show all the properties of the user class here --> 
</DataTemplate> 
<DataTemplate DataType="{x:Type local:User}"> 
    <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource UserTemplate}"/> 
</DataTemplate> 
<DataTemplate DataType="{x:Type local:Author}"> 
    <StackPanel> 
    <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource UserTemplate}"/> 
    <!-- show all the additional Author properties here --> 
    </StackPanel> 
</DataTemplate> 

Comme vous pouvez le voir, les deux DataTemplates pour l'utilisateur et pour commencer Auteur à l'aide du DataTemplate appelé « UserTemplate ». Mais dans l'auteur DataTemplate, nous ajouterons des propriétés spécifiques à l'auteur.

J'espère que cela aide.

+0

Cela aide en effet. Merci beaucoup pour votre explication très claire. Je pense que vous avez également par inadvertance répondu à une autre de mes questions posées ici: http://stackoverflow.com/questions/4355045/-there-quelquechose-en-wpf-similar-to-style-basedon-for-datatemplate/4356909 # 4356909 Je vais modifier le post pour vous donner un crédit. – Sheridan

+0

Toujours heureux d'aider :) – Liz