1
votes

I have a ListBox with a Canvas as ItemsPanel.

<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>

The problem is that whenever I add a new item to Items, which Listbox is binding to, it only shows that new item on screen. All previous items in the list are not shown. I can see that all the items are indeed in the Items list, and ListBoxItems are added to the visual tree. But I cannot see them. Only the last item added.

This is what it looks like running (only ever one item is shown)

enter image description here

This is what it looks like in designer and how it should look like running

enter image description here

Any suggestions?

UPDATE 1

The code the designer uses is this

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);

        ... 

    }
}

And the real code that adds to Items (ObservableCollection) is this. It's part of a Drag-n-drop operation.

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);
1
Is Items a List or an ObservableCollection? Your code works fine for me.15ee8f99-57ff-4f92-890c-b56153
You should also show the code that actually adds items. How does it differ from the design mode code?Clemens
@EdPlunkett It's an ObservableCollection, please see my updatesmok
@Clemens Added the code for adding in design and runningsmok
How are you ruling out the possibility that there are two instances of DrawingPanelViewModel? Another possibility I'd look into is that maybe comp is the same object every time.15ee8f99-57ff-4f92-890c-b56153

1 Answers

1
votes

The XAML works fine, and you've confirmed that there's only one copy of the viewmodel created, hence only one Items collection, and the first drop works.

Looking at your code, what jumps out at me is this line:

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

That's not creating a DrawingComponent; it's pulling one out of a hat that something else put it into. I'd put a breakpoint in there and see if you're actually getting multiple items in Items, but they're all the same actual object instance, with the same property values.

Or I'd just go straight to the code that starts the drag, and make sure you're creating a new DrawingComponent every time -- or else create a clone each time on the drop end. Doing it on the drag end seems better though, because then you can drag different subclasses of DrawingComponent from different sources and the drop code doesn't need to worry about it.