2017-08-31 1 views
1

J'ai un ListBox avec un Canvas comme ItemsPanel.WPF zone de liste avec toile montrant seulement le dernier élément

<UserControl.Resources> 
    <DataTemplate x:Key="itemTemplate"> 
     <Border BorderBrush="LightBlue" BorderThickness="1"> 
      <Grid Margin="0,2,2,2" Width="{Binding Width}" Height="{Binding Height}"> 
       <Rectangle Cursor="Hand" Fill="AliceBlue" 
         MouseDown="Rectangle_MouseDown" 
         MouseMove="Rectangle_MouseMove" 
         MouseUp="Rectangle_MouseUp"/> 
       <Label Content="{Binding Name}" Margin="5" IsHitTestVisible="False"/> 
      </Grid> 
     </Border> 
    </DataTemplate> 
</UserControl.Resources> 

<ListBox ItemsSource="{Binding Items}" 
     x:Name="listBox" 
     SelectionMode="Extended" 
     ItemTemplate="{StaticResource itemTemplate}"> 


    <ListBox.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Canvas Background="Transparent"/> 
     </ItemsPanelTemplate> 
    </ListBox.ItemsPanel> 

    <ListBox.ItemContainerStyle> 
     <Style TargetType="ListBoxItem"> 
      <Setter Property="Canvas.Left" Value="{Binding X}"/> 
      <Setter Property="Canvas.Top" Value="{Binding Y}"/> 
     </Style> 
    </ListBox.ItemContainerStyle> 
</ListBox> 

Le problème est que chaque fois que j'ajouter un nouvel élément à des éléments qui Listbox lie à, il montre seulement que nouvel élément à l'écran. Tous les éléments précédents de la liste ne sont pas affichés. Je peux voir que tous les éléments sont en effet dans la liste Items, et ListBoxItems sont ajoutés à l'arbre visuel. Mais je ne peux pas les voir. Seul le dernier élément ajouté.

C'est ce qu'il ressemble à courir (jamais qu'un seul élément est représenté)

enter image description here

C'est ce qu'il ressemble dans le concepteur et comment il devrait ressembler à courir

enter image description here

Des suggestions?

MISE À JOUR 1

Le code est le concepteur utilise ce

public class DrawingPanelViewModelMockup: DrawingPanelViewModel 
{ 
    public DrawingPanelViewModelMockup() 
    { 
     //Pc subclasses DrawingComponent 
     var pc = new Pc(); 
     pc.Name = "PC"; 
     pc.X = 20; 
     pc.Y = 40; 
     pc.Width = 100; 
     pc.Height = 50; 
     Items.Add(pc); 

     ... 

    } 
} 

Et le code réel qui ajoute aux éléments (ObservableCollection) est la suivante. Cela fait partie d'une opération Drag-n-drop.

var comp = e.Data.GetData(typeof(DrawingComponent).FullName) as DrawingComponent; 
var drawingPanelVm = ServiceLocator.Current.GetInstance<DrawingPanelViewModel>(); 
comp.X = mousePos.X; 
comp.Y = mousePos.Y; 
comp.Width = 100; 
comp.Height = 50; 
drawingPanelVm.Items.Add(comp); 
+0

Est-ce que les éléments sont une liste ou une collection observable? Votre code fonctionne bien pour moi. –

+1

Vous devez également afficher le code qui ajoute réellement des éléments. En quoi diffère-t-il du code de mode de conception? – Clemens

+0

@EdPlunkett C'est une ObservableCollection, s'il vous plaît voir ma mise à jour – smok

Répondre

1

Le XAML fonctionne très bien, et vous avez confirmé qu'il n'y a qu'une seule copie du viewmodel créé, d'où une seule Items collection, et la première goutte fonctionne.

En regardant votre code, ce qui me saute aux yeux est cette ligne:

var comp = e.Data.GetData(typeof(DrawingComponent).FullName) as DrawingComponent; 

Ce ne crée pas un DrawingComponent; c'est en retirer un chapeau que quelque chose d'autre a mis dedans. Je mettrais un point d'arrêt là-bas et je verrais si vous obtenez plusieurs éléments dans Items, mais ils sont tous identiques, avec les mêmes valeurs de propriété.

Ou je venais de rendre directement au code qui commence la traînée, et assurez-vous que vous créez un nouveau DrawingComponent chaque fois - ou bien créer un clone à chaque fois sur la fin de chute. Le faire sur la fin de traînée semble mieux, car alors vous pouvez faire glisser différentes sous-classes de DrawingComponent de différentes sources et le code de baisse n'a pas besoin de s'inquiéter à ce sujet.