2010-07-22 18 views
1

J'ai écrit un simple UserControl UpDown pour mon application. Je le restitue dans un ListBox afin que les contrôles UpDown soient ajoutés, ils s'empilent horizontalement.ListBox ItemTemplate est capricieux avec les données CLR et UserControl

Mon UserControl a un DependencyProperty qui correspond au nombre à l'intérieur du contrôle UpDown, appelé NumberProperty.

J'ajoute plusieurs contrôles UpDown à la ListBox via la liaison de données, où ItemsSource pour le ListBox est simplement un ObservableCollection<NumberGroup> appelé NumberGroups. Chaque NumberGroup a juste un membre appelé Number, et je veux que ce nombre apparaisse dans son contrôle UpDown respectif quand le ListBox est rendu.

Mon ListBox est défini dans XAML comme ceci:

<ListBox Grid.Row="1" ItemsSource="{Binding NumberGroups}" ItemTemplate="{StaticResource NumberGroupTemplate}"> 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal" Width="Auto" Height="Auto" /> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 
    </ListBox> 

et le DataTemplate pour le ListBox est:

<DataTemplate x:Key="RackTemplate"> 
     <StackPanel Orientation="Vertical"> 
      <TextBlock>Group</TextBlock> 
      <updown:UpDown Number="{Binding Number}" /> 
     </StackPanel> 
    </DataTemplate> 

Il est un peu confus parce que je nommé DependencyProperty Number dans le UpDown UserControl la Identique à la propriété de la classe NumberGroup. NumberGroup est simplement:

public class NumberGroup 
{ 
    public int Number { get; set; } 
} 

Quand je lance l'application, je le sais déjà ne va pas travailler parce que la fenêtre de sortie me dit:

System.Windows.Data Error: 39 : BindingExpression path error: 'Number' property not found on 'object' ''UpDown' (Name='')'. BindingExpression:Path=Number; DataItem='UpDown' (Name=''); target element is 'UpDown' (Name=''); target property is 'Number' (type 'Int32') 

OK, il est donc liaison au UserControl au lieu du ListItem ... qui ne peut pas être écrit. Donc, en tant que test, j'ai supprimé le DataTemplate de la définition Resources et ListBox et l'ai réexécuté. Dans le ListBox, j'ai eu un tas de NumberGroup s, ce qui est exactement ce que je m'attendais!

Alors, comment cela se fait-il quand je fais cela, il semble se lier à l'ListItem, mais quand je définis le ItemTemplate, il veut se lier au contrôle UpDown? Toute explication serait vraiment appréciée. J'ai parcouru les articles du Dr. WPF et je ne vois pas pourquoi cela arriverait.

MISE À JOUR

Ok, j'ai compris quelque chose lié à mon problème. Dans UserControl, je mets le DataContext à lui-même, de sorte que je puisse traiter les ICommand qui traitent avec les boutons Haut et Bas. Mais pour une raison que je ne comprends pas encore, ça gâche la liaison de données pour le ListItem! Pourquoi cela se produirait-il si UserControl est contenu dans ListItem?

Répondre

1

Lorsque vous définissez en interne DataContext du UserControl se vous obtenez exactement le même effet que si vous avez fait ceci:

<updown:UpDown DataContext="{Binding RelativeSource={RelativeSource Self}}" /> 

Il est évident que maintenant toutes les liaisons que vous définissez qui ont aucune source explicite défini utilisera la UpDown contrôle comme leur contexte. Ainsi, lorsque vous essayez de vous lier à la propriété Number, vous recherchez une propriété Number sur UpDown à la place des données de votre ListBoxItem. C'est exactement ce que votre erreur vous dit. Pour éviter cela, modifiez votre paramètre DataContext dans votre UserControl pour l'appliquer à un élément à l'intérieur du contrôle, comme une grille de disposition racine avec un x: Name.

<Grid x:Name="LayoutRoot"> 
... 
</Grid> 

Et de définir DataContext soit dans le code ou XAML.

LayoutRoot.DataContext = this; 
+0

merci pour le pourboire! Comme vous l'avez dit, cela supprime le message d'erreur indiquant que la liaison était vers le contrôle utilisateur UpDown au lieu des données CLR. Maintenant, mon problème est que je ne peux pas définir le texte dans mon contrôle UpDown. J'ai un 'DependencyProperty' pour Number, parce que je voudrais faire quelque chose comme' ', mais cela ne semble pas fonctionner. Même le codage en dur 'Number' ne fonctionne pas, donc je suppose que mon DependencyProperty ne fonctionne pas (mais cela fonctionne en interne, parce que mes commandes de bouton haut et bas peuvent changer la valeur du nombre!) – Dave

+0

intéressant, j'ai mis mon contrôle dans une application de test , et le réglage du nombre via la fenêtre a bien fonctionné ... mais le réglage à partir de mon UserControl (j'ai un UserControl dans un UserControl) ne fonctionne pas. – Dave

+0

erreur de codeur stupide, tout fonctionne très bien, merci encore pour votre astuce utile! – Dave